DeploySEALED
◆╳●#╳◇◇◆□@╳%●◆%◇╲$◆%?~^**~■##╳░▪?▪□?○◇▪!#?╱■╲#&░▓%●░$■╱░!?░▓▪^□◆
Transaction ID
Execution Fee
0.00000599 FLOWTransaction Summary
DeployContract deployment
Contract deployment
Script Arguments
0nameString
PinPin
1codeString
import FlowTransactionScheduler from 0xe467b9dd11fa00df
import FlowToken from 0x1654653399040a61
import FungibleToken from 0xf233dcee88fe0abe
access(all) contract PinPin {
// -----------------------------------------------------------------------
// PinPin contract-level fields.
// These contain actual values that are stored in the smart contract.
// -----------------------------------------------------------------------
access(all) var subscriptionFee: UFix64
// Events
access(all) event ContractInitialized()
access(all) event SubscriptionActivated(subscriber: Address)
// -----------------------------------------------------------------------
// PinPin account paths
// -----------------------------------------------------------------------
access(all) let SubscriptionStoragePath: StoragePath
access(all) let SubscriptionPublicPath: PublicPath
access(all) let handlerStoragePath: StoragePath
// access(all) let feeVaultStoragePath: StoragePath
// access(all) let receiptsStoragePath: StoragePath
// -----------------------------------------------------------------------
// PinPin contract-level Composite Type definitions
// -----------------------------------------------------------------------
// Subscription resource
// This resource is used to store the subscription information
access(all) resource Subscription {
access(all) let subscriber: Address
access(all) let fee: UFix64
access(all) let cycles: UFix64
access(all) let startedAt: UFix64
access(all) let expiresAt: UFix64
init(subscriber: Address, fee: UFix64, cycles: UFix64, startedAt: UFix64, expiresAt: UFix64) {
self.subscriber = subscriber
self.fee = fee
self.cycles = cycles
self.startedAt = startedAt
self.expiresAt = expiresAt
}
}
// Subscription manager
// This storage is used to store and manage the subscriptions
// inside a user's account
access(all) resource SubscriptionManager {
access(all) var subscriptions: @[Subscription]
init() {
self.subscriptions <- []
}
}
// -----------------------------------------------------------------------
/// Handler resource that implements the Scheduled Transaction interface
access(all) resource Handler: FlowTransactionScheduler.TransactionHandler {
access(self) var feeVault: @FlowToken.Vault
access(self) var receipts: @[FlowTransactionScheduler.ScheduledTransaction]
access(FlowTransactionScheduler.Execute) fun executeTransaction(id: UInt64, data: AnyStruct?) {
// Get PinPin's Flow vault ref
let pinPinVault = PinPin.account.capabilities.borrow<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)!
// Get a reference to the vaultCap
// let ref <- self.feeVault.withdraw(amount: 0.1)
// Deposit 0 Flow on the PinPin account
pinPinVault.deposit(from: <- self.feeVault.withdraw(amount: 0.1))
log("Account /self.owner!.address has made a deposit for a subscription")
emit SubscriptionActivated(subscriber: self.owner!.address)
// Determine delay for the next transaction (default 3 seconds if none provided)
var delay: UFix64 = 60.0
if data != nil {
let t = data!.getType()
if t.isSubtype(of: Type<UFix64>()) {
delay = data as! UFix64
}
}
let future = getCurrentBlock().timestamp + delay
let priority = FlowTransactionScheduler.Priority.Medium
let executionEffort: UInt64 = 1000
let estimate = FlowTransactionScheduler.estimate(
data: data,
timestamp: future,
priority: priority,
executionEffort: executionEffort
)
assert(
estimate.timestamp != nil || priority == FlowTransactionScheduler.Priority.Low,
message: estimate.error ?? "estimation failed"
)
// Withdraw FLOW fees from this resource's ownner account vault
let fees <- self.feeVault.withdraw(amount: estimate.flowFee ?? 0.0) as! @FlowToken.Vault
// Issue a capability to the handler stored in this contract account
let handlerCap = PinPin.account.capabilities.storage
.issue<auth(FlowTransactionScheduler.Execute) &{FlowTransactionScheduler.TransactionHandler}>(/storage/PinPin)
let receipt: @FlowTransactionScheduler.ScheduledTransaction <- FlowTransactionScheduler.schedule(
handlerCap: handlerCap,
data: data,
timestamp: future,
priority: priority,
executionEffort: executionEffort,
fees: <-fees
)
log("Loop transaction id: ".concat(receipt.id.toString()).concat(" at ").concat(receipt.timestamp.toString()))
destroy receipt
}
init(_ vault: @FlowToken.Vault,_ consentedFee: UFix64,_ consentedCycles: UFix64) {
pre {
PinPin.subscriptionFee == consentedFee: "Consented fee must be equal to contract's current fee"
vault.balance >= consentedCycles * consentedFee: "Vault's balance must be equal or greater than Fees x Cycles"
}
self.feeVault <- vault
self.receipts <- []
}
}
/// Factory for the handler resource
access(all) fun createHandler(vault: @FlowToken.Vault, consentedFee: UFix64, consentedCycles: UFix64): @Handler {
return <- create Handler(<- vault, consentedFee, consentedCycles)
}
init() {
self.subscriptionFee = 0.1
// Set the named paths
let identifier = "PinPin_".concat(self.account.address.toString())
self.SubscriptionStoragePath = StoragePath(identifier: identifier)!
self.SubscriptionPublicPath = PublicPath(identifier: identifier)!
self.handlerStoragePath = StoragePath(identifier: identifier)!
emit ContractInitialized()
}
}
Cadence Script
1transaction(name: String, code: String ) {
2 prepare(signer: auth(AddContract) &Account) {
3 signer.contracts.add(name: name, code: code.utf8 )
4 }
5 }