DeploySEALED
□◆●^◆▫#@╲*&▫&▓*~○&◇▪&◆□$@░$◆@╳░?◇█▫&▪●*▓╳╳□%◆%◇#%▒○╲╱!~▪!$◆▪*■▫!
Transaction ID
Execution Fee
0.00222 FLOWTransaction Summary
DeployContract deployment
Contract deployment
Script Arguments
0nameString
StreamVestScheduler
1codeString
// StreamVestScheduler.cdc
// Companion contract that integrates StreamVest with Flow's
// scheduled-transaction infrastructure for autonomous streaming.
//
// Deployed alongside StreamVest — calls the public triggerStream()
// function on schedule so tokens flow automatically.
import FlowTransactionScheduler from 0xe467b9dd11fa00df
import StreamVest from 0x5ec90e3dcf0067c4
import FlowToken from 0x1654653399040a61
import FungibleToken from 0xf233dcee88fe0abe
access(all) contract StreamVestScheduler {
// ───────── Events ─────────
access(all) event HandlerCreated(nftID: UInt64, collectionAddress: Address, intervalSeconds: UFix64)
access(all) event StreamTriggered(nftID: UInt64)
access(all) event HandlerCompleted(nftID: UInt64)
access(all) event FeesLow(nftID: UInt64, remainingFees: UFix64)
// ═══════════════════════════════════════════════════════════════════
// ScheduledStreamHandler
// ═══════════════════════════════════════════════════════════════════
access(all) resource ScheduledStreamHandler: FlowTransactionScheduler.TransactionHandler {
access(self) let collectionAddress: Address
access(self) let nftID: UInt64
access(self) let intervalSeconds: UFix64
access(all) var isComplete: Bool
access(self) var feeVault: @FlowToken.Vault
access(self) var selfCap: Capability<auth(FlowTransactionScheduler.Execute) &{FlowTransactionScheduler.TransactionHandler}>?
init(
collectionAddress: Address,
nftID: UInt64,
intervalSeconds: UFix64,
feeVault: @FlowToken.Vault
) {
self.collectionAddress = collectionAddress
self.nftID = nftID
self.intervalSeconds = intervalSeconds
self.isComplete = false
self.feeVault <- feeVault
self.selfCap = nil
}
/// Must be called once after storing the handler and issuing its capability.
access(all) fun setSelfCapability(
cap: Capability<auth(FlowTransactionScheduler.Execute) &{FlowTransactionScheduler.TransactionHandler}>
) {
pre { self.selfCap == nil: "Self capability already set" }
self.selfCap = cap
}
/// Called by the Flow blockchain at each scheduled interval.
access(FlowTransactionScheduler.Execute) fun executeTransaction(id: UInt64, data: AnyStruct?) {
if self.isComplete { return }
// Borrow the public collection from the owner's account.
let account = getAccount(self.collectionAddress)
let collection = account.capabilities
.get<&StreamVest.Collection>(StreamVest.CollectionPublicPath)
.borrow()
?? panic("StreamVestScheduler: cannot borrow collection at ".concat(self.collectionAddress.toString()))
// Deliver vested tokens to the destination.
collection.triggerStream(nftID: self.nftID)
emit StreamTriggered(nftID: self.nftID)
// Check if the stream is finished.
if let nft = collection.borrowStreamVestNFT(id: self.nftID) {
if !nft.isActive {
self.isComplete = true
emit HandlerCompleted(nftID: self.nftID)
return
}
} else {
// NFT no longer in collection.
self.isComplete = true
emit HandlerCompleted(nftID: self.nftID)
return
}
// ── Reschedule for the next interval ──
let nextTime = getCurrentBlock().timestamp + self.intervalSeconds
let priority = FlowTransactionScheduler.Priority(rawValue: 0)!
let est = FlowTransactionScheduler.estimate(
data: nil,
timestamp: nextTime,
priority: priority,
executionEffort: 1000
)
let fee = est.flowFee ?? 0.0
if fee == 0.0 || self.feeVault.balance < fee {
emit FeesLow(nftID: self.nftID, remainingFees: self.feeVault.balance)
return
}
let fees <- self.feeVault.withdraw(amount: fee) as! @FlowToken.Vault
let receipt <- FlowTransactionScheduler.schedule(
handlerCap: self.selfCap!,
data: nil,
timestamp: nextTime,
priority: priority,
executionEffort: 1000,
fees: <- fees
)
destroy receipt
}
/// How much FLOW remains for scheduling fees.
access(all) view fun getFeeBalance(): UFix64 {
return self.feeVault.balance
}
/// Top up the fee vault so the handler can keep rescheduling.
access(all) fun depositFees(from: @FlowToken.Vault) {
self.feeVault.deposit(from: <- from)
}
}
// ═══════════════════════════════════════════════════════════════════
// Factory
// ═══════════════════════════════════════════════════════════════════
access(all) fun createHandler(
collectionAddress: Address,
nftID: UInt64,
intervalSeconds: UFix64,
feeVault: @FlowToken.Vault
): @ScheduledStreamHandler {
emit HandlerCreated(
nftID: nftID,
collectionAddress: collectionAddress,
intervalSeconds: intervalSeconds
)
return <- create ScheduledStreamHandler(
collectionAddress: collectionAddress,
nftID: nftID,
intervalSeconds: intervalSeconds,
feeVault: <- feeVault
)
}
init() {}
}
Cadence Script
1transaction(name: String, code: String ) {
2 prepare(signer: auth(AddContract) &Account) {
3 signer.contracts.add(name: name, code: code.utf8 )
4 }
5 }