DeploySEALED

○#^□╳@&~%■!■!█*╳▫█%●█&*╱◇~◆○■▫▒◇▓@$#▪▪*▓?▫#■#░▫&▒╳&▪□◆&^○▓░■$^╲○

Transaction ID

Timestamp

Aug 16, 2025, 09:47:29 PM UTC
6mo ago

Block Height

123,173,933

Computation

0

Execution Fee

0.00000599 FLOW

Transaction Summary

Deploy

Contract deployment

Contract deployment

Script Arguments

0nameString
PayAsYouGoBilling
1codeString
import FungibleToken from 0xf233dcee88fe0abe access(all) contract PayAsYouGoBilling { /// Storage and public paths for user allowances access(all) let AllowanceStoragePath: StoragePath access(all) let AllowancePublicPath: PublicPath /// Minimal interface exposed to providers for charging access(all) resource interface Charge { access(all) fun charge(amount: UFix64) access(all) view fun getRemainingCapacity(): UFix64 access(all) view fun getConfig(): PayAsYouGoBilling.Config } /// Immutable configuration for an allowance access(all) struct Config { access(all) let minCharge: UFix64 access(all) let monthlyMax: UFix64 access(all) let periodSeconds: UFix64 access(all) let vaultType: Type access(all) let user: Address access(all) let provider: Address init( minCharge: UFix64, monthlyMax: UFix64, periodSeconds: UFix64, vaultType: Type, user: Address, provider: Address ) { pre { minCharge > 0.0: "minCharge must be > 0" monthlyMax >= minCharge: "monthlyMax must be >= minCharge" periodSeconds > 0.0: "periodSeconds must be > 0" } self.minCharge = minCharge self.monthlyMax = monthlyMax self.periodSeconds = periodSeconds self.vaultType = vaultType self.user = user self.provider = provider } } /// Allowance resource held by the USER, callable by the PROVIDER through a public capability access(all) resource Allowance: Charge { /// Capability to withdraw from the user's vault of the configured token access(contract) let userVaultCap: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}> /// Capability for the provider's receiver to receive the configured token access(contract) let providerReceiverCap: Capability<&{FungibleToken.Receiver}> /// Configuration snapshot access(all) let config: PayAsYouGoBilling.Config /// Rolling period tracking access(contract) var periodStartTimestamp: UFix64 access(contract) var chargedThisPeriod: UFix64 init( userVaultCap: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>, providerReceiverCap: Capability<&{FungibleToken.Receiver}>, config: PayAsYouGoBilling.Config ) { // Validate caps and type matching let userVault = userVaultCap.borrow() ?? panic("Invalid user vault capability") let providerReceiver = providerReceiverCap.borrow() ?? panic("Invalid provider receiver capability") if userVault.getType().identifier != providerReceiver.getType().identifier { panic("Mismatched token types") } if userVault.getType().identifier != config.vaultType.identifier { panic("Config vault type mismatch") } self.userVaultCap = userVaultCap self.providerReceiverCap = providerReceiverCap self.config = config self.periodStartTimestamp = getCurrentBlock().timestamp self.chargedThisPeriod = 0.0 } /// Ensure the rolling period is correctly maintained and reset when elapsed access(contract) fun ensurePeriodFresh() { let now: UFix64 = getCurrentBlock().timestamp if now >= self.periodStartTimestamp + self.config.periodSeconds { self.periodStartTimestamp = now self.chargedThisPeriod = 0.0 } } /// Returns the remaining capacity for this period (after refreshing the window) access(all) view fun getRemainingCapacity(): UFix64 { let now: UFix64 = getCurrentBlock().timestamp let periodEnd: UFix64 = self.periodStartTimestamp + self.config.periodSeconds if now >= periodEnd { return self.config.monthlyMax } if self.chargedThisPeriod >= self.config.monthlyMax { return 0.0 } return self.config.monthlyMax - self.chargedThisPeriod } /// Returns immutable configuration access(all) view fun getConfig(): PayAsYouGoBilling.Config { return self.config } /// Provider-triggered charge respecting min per-charge and monthly cap access(all) fun charge(amount: UFix64) { // Validate against current period capacity without mutating if amount < self.config.minCharge { panic("Amount below minCharge") } if amount > self.getRemainingCapacity() { panic("Amount exceeds remaining capacity for this period") } // Refresh period and perform the charge self.ensurePeriodFresh() let vault <- self.userVaultCap.borrow()!.withdraw(amount: amount) self.providerReceiverCap.borrow()!.deposit(from: <-vault) self.chargedThisPeriod = self.chargedThisPeriod + amount } } /// Create a new allowance. Caller should save it and link a public capability restricted to Charge access(all) fun createAllowance( userVaultCap: Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Vault}>, providerReceiverCap: Capability<&{FungibleToken.Receiver}>, minCharge: UFix64, monthlyMax: UFix64, periodSeconds: UFix64, user: Address, provider: Address ): @PayAsYouGoBilling.Allowance { let vt = userVaultCap.borrow() ?? panic("Invalid user vault cap when creating allowance") let config = PayAsYouGoBilling.Config( minCharge: minCharge, monthlyMax: monthlyMax, periodSeconds: periodSeconds, vaultType: vt.getType(), user: user, provider: provider ) return <- create PayAsYouGoBilling.Allowance( userVaultCap: userVaultCap, providerReceiverCap: providerReceiverCap, config: config ) } init() { self.AllowanceStoragePath = StoragePath(identifier: "paygAllowance")! self.AllowancePublicPath = PublicPath(identifier: "paygAllowance")! } }

Cadence Script

1transaction(name: String, code: String ) {
2		prepare(signer: auth(AddContract) &Account) {
3			signer.contracts.add(name: name, code: code.utf8 )
4		}
5	}