diff --git a/.env.development b/.env.development index c8f8ad1..ded8d6c 100644 --- a/.env.development +++ b/.env.development @@ -3,10 +3,6 @@ # We recommend to use the service account defined in the flow.json file your emulator is using. FLOW_INIT_ACCOUNTS=0 -CONTRACT_FUNGIBLE_TOKEN=0xee82856bf20e2aa6 -CONTRACT_FLOW_TOKEN=0x0ae53cb6e3f42a79 -CONTRACT_FUSD=0xf8d6e0586b0a20c7 -CONTRACT_FCL_CRYPTO=0xf8d6e0586b0a20c7 FLOW_AVATAR_URL=https://avatars.onflow.org/avatar/ # EMULATOR REST API ENDPOINT diff --git a/.env.example b/.env.example index 820d846..bffaeef 100644 --- a/.env.example +++ b/.env.example @@ -3,10 +3,6 @@ # We recommend to use the service account definied in the flow.json file your emulator is using. FLOW_INIT_ACCOUNTS=0 -CONTRACT_FUNGIBLE_TOKEN=0xee82856bf20e2aa6 -CONTRACT_FLOW_TOKEN=0x0ae53cb6e3f42a79 -CONTRACT_FUSD=0xf8d6e0586b0a20c7 -CONTRACT_FCL_CRYPTO=0xf8d6e0586b0a20c7 FLOW_AVATAR_URL=https://avatars.onflow.org/avatar/ # EMULATOR REST API ENDPOINT diff --git a/cadence/contracts/FCL.cdc b/cadence/contracts/FCL.cdc index 56950f3..a8fe8b2 100644 --- a/cadence/contracts/FCL.cdc +++ b/cadence/contracts/FCL.cdc @@ -1,12 +1,24 @@ -pub contract FCL { - pub let storagePath: StoragePath +access(all) contract FCL { + access(all) let storagePath: StoragePath - pub struct Account { - pub let type: String - pub let address: Address - pub let keyId: Int - pub var label: String - pub var scopes: [String] + access(all) struct FCLKey { + access(all) let publicKey: [UInt8] + access(all) let signatureAlgorithm: UInt8 + access(all) let hashAlgorithm: UInt8 + + init(publicKey: [UInt8], signatureAlgorithm: UInt8, hashAlgorithm: UInt8) { + self.publicKey = publicKey + self.signatureAlgorithm = signatureAlgorithm + self.hashAlgorithm = hashAlgorithm + } + } + + access(all) struct FCLAccount { + access(all) let type: String + access(all) let address: Address + access(all) let keyId: Int + access(all) var label: String + access(all) var scopes: [String] init(address: Address, label: String, scopes: [String]) { self.type = "ACCOUNT" @@ -16,59 +28,74 @@ pub contract FCL { self.scopes = scopes } - pub fun update(label: String, scopes: [String]) { + access(all) fun update(label: String, scopes: [String]) { self.label = label self.scopes = scopes } } - pub resource Root { - pub let key: [UInt8] - pub let accounts: {Address: Account} + access(all) resource Root { + access(all) let key: FCLKey + access(all) let accounts: {Address: FCLAccount} - init (_ key: String) { - self.key = key.decodeHex() + init (_ key: FCLKey) { + self.key = key self.accounts = {} } - pub fun add(_ acct: Account) { + access(all) fun add(_ acct: FCLAccount) { self.accounts[acct.address] = acct } - pub fun update(address: Address, label: String, scopes: [String]) { + access(all) fun update(address: Address, label: String, scopes: [String]) { let acct = self.accounts[address] acct!.update(label: label, scopes: scopes) self.accounts[address] = acct } } - pub fun accounts(): {Address: Account} { - return self.account.borrow<&Root>(from: self.storagePath)!.accounts + access(all) fun accounts(): &{Address: FCLAccount} { + return self.account.storage.borrow<&Root>(from: self.storagePath)!.accounts } - pub fun getServiceKey(): [UInt8] { - return self.account.borrow<&Root>(from: self.storagePath)!.key + access(all) fun getServiceKey(): &FCLKey { + return self.account.storage.borrow<&Root>(from: self.storagePath)!.key } - pub fun new(label: String, scopes: [String], address: Address?): AuthAccount { - let acct = AuthAccount(payer: self.account) - acct.addPublicKey(self.getServiceKey()) + access(all) fun new(label: String, scopes: [String], address: Address?): &Account { + let acct = Account(payer: self.account) + let key = self.getServiceKey() + + acct.keys.add( + publicKey: PublicKey( + publicKey: key.publicKey.map(fun (_ byte: UInt8): UInt8 { + return byte + }), + signatureAlgorithm: SignatureAlgorithm(key.signatureAlgorithm)!, + ), + hashAlgorithm: HashAlgorithm(key.hashAlgorithm)!, + weight: 1000.0 + ) self.account + .storage .borrow<&Root>(from: self.storagePath)! - .add(Account(address: address ?? acct.address, label: label, scopes: scopes)) + .add(FCLAccount(address: address ?? acct.address, label: label, scopes: scopes)) return acct } - pub fun update(address: Address, label: String, scopes: [String]) { - self.account.borrow<&Root>(from: self.storagePath)! + access(all) fun update(address: Address, label: String, scopes: [String]) { + self.account.storage.borrow<&Root>(from: self.storagePath)! .update(address: address, label: label, scopes: scopes) } - init (key: String, initAccountsLabels: [String]) { + init (publicKey: String, hashAlgorithm: UInt8, signAlgorithm: UInt8, initAccountsLabels: [String]) { + let keyByteArray = publicKey.decodeHex() + let key = FCLKey(publicKey: keyByteArray, signatureAlgorithm: signAlgorithm, hashAlgorithm: hashAlgorithm) + self.storagePath = /storage/FCL_DEV_WALLET - self.account.save(<- create Root(key), to: self.storagePath) + self.account.storage.save(<- create Root(key), to: self.storagePath) self.new(label: initAccountsLabels[0], scopes: [], address: self.account.address) var acctInitIndex = 1 diff --git a/cadence/contracts/FCLCrypto.cdc b/cadence/contracts/FCLCrypto.cdc index ebebb20..8fde29c 100644 --- a/cadence/contracts/FCLCrypto.cdc +++ b/cadence/contracts/FCLCrypto.cdc @@ -1,6 +1,21 @@ -pub contract FCLCrypto { - - pub fun verifyUserSignatures( +/* + FCLCrypto + + The FCLCrypto contract provides functions which allow to verify signatures and check for signing power. +*/ + +access(all) contract FCLCrypto { + + /// verifyUserSignatures allows to verify the user signatures for the given account. + /// + /// @param address: The address of the account + /// @param message: The signed data + /// @param keyIndices: This integer array maps the signatures to the account keys by index + /// @param signatures: The signatures belonging to the account keys + /// + /// @return Whether all signatures are valid and the combined total key weight reaches signing power + /// + access(all) fun verifyUserSignatures( address: Address, message: String, keyIndices: [Int], @@ -15,7 +30,16 @@ pub contract FCLCrypto { ) } - pub fun verifyAccountProofSignatures( + /// verifyAccountProofSignatures allows to verify the account proof signatures for the given account. + /// + /// @param address: The address of the account + /// @param message: The signed data + /// @param keyIndices: This integer array maps the signatures to the account keys by index + /// @param signatures: The signatures belonging to the account keys + /// + /// @return Whether all signatures are valid and the combined total key weight reaches signing power + /// + access(all) fun verifyAccountProofSignatures( address: Address, message: String, keyIndices: [Int], @@ -37,7 +61,18 @@ pub contract FCLCrypto { ) } - priv fun verifySignatures( + /// verifySignatures is a private function which provides the functionality to verify + /// signatures for the public functions. + /// + /// @param address: The address of the account + /// @param message: The signed data + /// @param keyIndices: This integer array maps the signatures to the account keys by index + /// @param signatures: The signatures belonging to the account keys + /// @param domainSeparationTag: The domain tag originally used for the signatures + /// + /// @return Whether all signatures are valid and the combined total key weight reaches signing power + /// + access(self) fun verifySignatures( address: Address, message: String, keyIndices: [Int], @@ -96,9 +131,9 @@ pub contract FCLCrypto { return totalWeight >= 1000.0 } - priv let domainSeparationTagFlowUser: String - priv let domainSeparationTagFCLUser: String - priv let domainSeparationTagAccountProof: String + access(self) let domainSeparationTagFlowUser: String + access(self) let domainSeparationTagFCLUser: String + access(self) let domainSeparationTagAccountProof: String init() { self.domainSeparationTagFlowUser = "FLOW-V0.0-user" diff --git a/cadence/contracts/FUSD.cdc b/cadence/contracts/FUSD.cdc deleted file mode 100644 index b75c8fb..0000000 --- a/cadence/contracts/FUSD.cdc +++ /dev/null @@ -1,226 +0,0 @@ -import FungibleToken from "./FungibleToken.cdc" - -pub contract FUSD: FungibleToken { - - // Event that is emitted when the contract is created - pub event TokensInitialized(initialSupply: UFix64) - - // Event that is emitted when tokens are withdrawn from a Vault - pub event TokensWithdrawn(amount: UFix64, from: Address?) - - // Event that is emitted when tokens are deposited to a Vault - pub event TokensDeposited(amount: UFix64, to: Address?) - - // Event that is emitted when new tokens are minted - pub event TokensMinted(amount: UFix64) - - // The storage path for the admin resource - pub let AdminStoragePath: StoragePath - - // The storage Path for minters' MinterProxy - pub let MinterProxyStoragePath: StoragePath - - // The public path for minters' MinterProxy capability - pub let MinterProxyPublicPath: PublicPath - - // Event that is emitted when a new minter resource is created - pub event MinterCreated() - - // Total supply of fusd in existence - pub var totalSupply: UFix64 - - // Vault - // - // Each user stores an instance of only the Vault in their storage - // The functions in the Vault are governed by the pre and post conditions - // in FungibleToken when they are called. - // The checks happen at runtime whenever a function is called. - // - // Resources can only be created in the context of the contract that they - // are defined in, so there is no way for a malicious user to create Vaults - // out of thin air. A special Minter resource needs to be defined to mint - // new tokens. - // - pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance { - - // holds the balance of a users tokens - pub var balance: UFix64 - - // initialize the balance at resource creation time - init(balance: UFix64) { - self.balance = balance - } - - // withdraw - // - // Function that takes an integer amount as an argument - // and withdraws that amount from the Vault. - // It creates a new temporary Vault that is used to hold - // the money that is being transferred. It returns the newly - // created Vault to the context that called so it can be deposited - // elsewhere. - // - pub fun withdraw(amount: UFix64): @FungibleToken.Vault { - self.balance = self.balance - amount - emit TokensWithdrawn(amount: amount, from: self.owner?.address) - return <-create Vault(balance: amount) - } - - // deposit - // - // Function that takes a Vault object as an argument and adds - // its balance to the balance of the owners Vault. - // It is allowed to destroy the sent Vault because the Vault - // was a temporary holder of the tokens. The Vault's balance has - // been consumed and therefore can be destroyed. - pub fun deposit(from: @FungibleToken.Vault) { - let vault <- from as! @FUSD.Vault - self.balance = self.balance + vault.balance - emit TokensDeposited(amount: vault.balance, to: self.owner?.address) - vault.balance = 0.0 - destroy vault - } - - destroy() { - FUSD.totalSupply = FUSD.totalSupply - self.balance - } - } - - // createEmptyVault - // - // Function that creates a new Vault with a balance of zero - // and returns it to the calling context. A user must call this function - // and store the returned Vault in their storage in order to allow their - // account to be able to receive deposits of this token type. - // - pub fun createEmptyVault(): @FUSD.Vault { - return <-create Vault(balance: 0.0) - } - - // Minter - // - // Resource object that can mint new tokens. - // The admin stores this and passes it to the minter account as a capability wrapper resource. - // - pub resource Minter { - - // mintTokens - // - // Function that mints new tokens, adds them to the total supply, - // and returns them to the calling context. - // - pub fun mintTokens(amount: UFix64): @FUSD.Vault { - pre { - amount > 0.0: "Amount minted must be greater than zero" - } - FUSD.totalSupply = FUSD.totalSupply + amount - emit TokensMinted(amount: amount) - return <-create Vault(balance: amount) - } - - } - - pub resource interface MinterProxyPublic { - pub fun setMinterCapability(cap: Capability<&Minter>) - } - - // MinterProxy - // - // Resource object holding a capability that can be used to mint new tokens. - // The resource that this capability represents can be deleted by the admin - // in order to unilaterally revoke minting capability if needed. - - pub resource MinterProxy: MinterProxyPublic { - - // access(self) so nobody else can copy the capability and use it. - access(self) var minterCapability: Capability<&Minter>? - - // Anyone can call this, but only the admin can create Minter capabilities, - // so the type system constrains this to being called by the admin. - pub fun setMinterCapability(cap: Capability<&Minter>) { - self.minterCapability = cap - } - - pub fun mintTokens(amount: UFix64): @FUSD.Vault { - return <- self.minterCapability! - .borrow()! - .mintTokens(amount:amount) - } - - init() { - self.minterCapability = nil - } - - } - - // createMinterProxy - // - // Function that creates a MinterProxy. - // Anyone can call this, but the MinterProxy cannot mint without a Minter capability, - // and only the admin can provide that. - // - pub fun createMinterProxy(): @MinterProxy { - return <- create MinterProxy() - } - - // Administrator - // - // A resource that allows new minters to be created - // - // We will only want one minter for now, but might need to add or replace them in future. - // The Minter/Minter Proxy structure enables this. - // Ideally we would create this structure in a single function, generate the paths from the address - // and cache all of this information to enable easy revocation but String/Path comversion isn't yet supported. - // - pub resource Administrator { - - // createNewMinter - // - // Function that creates a Minter resource. - // This should be stored at a unique path in storage then a capability to it wrapped - // in a MinterProxy to be stored in a minter account's storage. - // This is done by the minter account running: - // transactions/fusd/minter/setup_minter_account.cdc - // then the admin account running: - // transactions/fusd/admin/deposit_minter_capability.cdc - // - pub fun createNewMinter(): @Minter { - emit MinterCreated() - return <- create Minter() - } - - } - - init() { - self.AdminStoragePath = /storage/fusdAdmin - self.MinterProxyPublicPath = /public/fusdMinterProxy - self.MinterProxyStoragePath = /storage/fusdMinterProxy - - self.totalSupply = 0.0 - - let admin <- create Administrator() - - // Emit an event that shows that the contract was initialized - emit TokensInitialized(initialSupply: 0.0) - - let minter <- admin.createNewMinter() - - let mintedVault <- minter.mintTokens(amount: 1000000.0) - - destroy minter - - self.account.save(<-admin, to: self.AdminStoragePath) - - self.account.save(<-mintedVault, to: /storage/fusdVault) - - self.account.link<&FUSD.Vault{FungibleToken.Receiver}>( - /public/fusdReceiver, - target: /storage/fusdVault - ) - - self.account.link<&FUSD.Vault{FungibleToken.Balance}>( - /public/fusdBalance, - target: /storage/fusdVault - ) - } -} diff --git a/cadence/contracts/FungibleToken.cdc b/cadence/contracts/FungibleToken.cdc deleted file mode 100644 index 6fddb0e..0000000 --- a/cadence/contracts/FungibleToken.cdc +++ /dev/null @@ -1,199 +0,0 @@ -/** - -# The Flow Fungible Token standard - -## `FungibleToken` contract interface - -The interface that all fungible token contracts would have to conform to. -If a users wants to deploy a new token contract, their contract -would need to implement the FungibleToken interface. - -Their contract would have to follow all the rules and naming -that the interface specifies. - -## `Vault` resource - -Each account that owns tokens would need to have an instance -of the Vault resource stored in their account storage. - -The Vault resource has methods that the owner and other users can call. - -## `Provider`, `Receiver`, and `Balance` resource interfaces - -These interfaces declare pre-conditions and post-conditions that restrict -the execution of the functions in the Vault. - -They are separate because it gives the user the ability to share -a reference to their Vault that only exposes the fields functions -in one or more of the interfaces. - -It also gives users the ability to make custom resources that implement -these interfaces to do various things with the tokens. -For example, a faucet can be implemented by conforming -to the Provider interface. - -By using resources and interfaces, users of FungibleToken contracts -can send and receive tokens peer-to-peer, without having to interact -with a central ledger smart contract. To send tokens to another user, -a user would simply withdraw the tokens from their Vault, then call -the deposit function on another user's Vault to complete the transfer. - -*/ - -/// FungibleToken -/// -/// The interface that fungible token contracts implement. -/// -pub contract interface FungibleToken { - - /// The total number of tokens in existence. - /// It is up to the implementer to ensure that the total supply - /// stays accurate and up to date - /// - pub var totalSupply: UFix64 - - /// TokensInitialized - /// - /// The event that is emitted when the contract is created - /// - pub event TokensInitialized(initialSupply: UFix64) - - /// TokensWithdrawn - /// - /// The event that is emitted when tokens are withdrawn from a Vault - /// - pub event TokensWithdrawn(amount: UFix64, from: Address?) - - /// TokensDeposited - /// - /// The event that is emitted when tokens are deposited into a Vault - /// - pub event TokensDeposited(amount: UFix64, to: Address?) - - /// Provider - /// - /// The interface that enforces the requirements for withdrawing - /// tokens from the implementing type. - /// - /// It does not enforce requirements on `balance` here, - /// because it leaves open the possibility of creating custom providers - /// that do not necessarily need their own balance. - /// - pub resource interface Provider { - - /// withdraw subtracts tokens from the owner's Vault - /// and returns a Vault with the removed tokens. - /// - /// The function's access level is public, but this is not a problem - /// because only the owner storing the resource in their account - /// can initially call this function. - /// - /// The owner may grant other accounts access by creating a private - /// capability that allows specific other users to access - /// the provider resource through a reference. - /// - /// The owner may also grant all accounts access by creating a public - /// capability that allows all users to access the provider - /// resource through a reference. - /// - pub fun withdraw(amount: UFix64): @Vault { - post { - // `result` refers to the return value - result.balance == amount: - "Withdrawal amount must be the same as the balance of the withdrawn Vault" - } - } - } - - /// Receiver - /// - /// The interface that enforces the requirements for depositing - /// tokens into the implementing type. - /// - /// We do not include a condition that checks the balance because - /// we want to give users the ability to make custom receivers that - /// can do custom things with the tokens, like split them up and - /// send them to different places. - /// - pub resource interface Receiver { - - /// deposit takes a Vault and deposits it into the implementing resource type - /// - pub fun deposit(from: @Vault) - } - - /// Balance - /// - /// The interface that contains the `balance` field of the Vault - /// and enforces that when new Vaults are created, the balance - /// is initialized correctly. - /// - pub resource interface Balance { - - /// The total balance of a vault - /// - pub var balance: UFix64 - - init(balance: UFix64) { - post { - self.balance == balance: - "Balance must be initialized to the initial balance" - } - } - } - - /// Vault - /// - /// The resource that contains the functions to send and receive tokens. - /// - pub resource Vault: Provider, Receiver, Balance { - - // The declaration of a concrete type in a contract interface means that - // every Fungible Token contract that implements the FungibleToken interface - // must define a concrete `Vault` resource that conforms to the `Provider`, `Receiver`, - // and `Balance` interfaces, and declares their required fields and functions - - /// The total balance of the vault - /// - pub var balance: UFix64 - - // The conforming type must declare an initializer - // that allows prioviding the initial balance of the Vault - // - init(balance: UFix64) - - /// withdraw subtracts `amount` from the Vault's balance - /// and returns a new Vault with the subtracted balance - /// - pub fun withdraw(amount: UFix64): @Vault { - pre { - self.balance >= amount: - "Amount withdrawn must be less than or equal than the balance of the Vault" - } - post { - // use the special function `before` to get the value of the `balance` field - // at the beginning of the function execution - // - self.balance == before(self.balance) - amount: - "New Vault balance must be the difference of the previous balance and the withdrawn Vault" - } - } - - /// deposit takes a Vault and adds its balance to the balance of this Vault - /// - pub fun deposit(from: @Vault) { - post { - self.balance == before(self.balance) + before(from.balance): - "New Vault balance must be the sum of the previous balance and the deposited Vault" - } - } - } - - /// createEmptyVault allows any user to create a new Vault that has a zero balance - /// - pub fun createEmptyVault(): @Vault { - post { - result.balance == 0.0: "The newly created Vault must have zero balance" - } - } -} diff --git a/cadence/contracts/utility/FlowToken.cdc b/cadence/contracts/utility/FlowToken.cdc new file mode 100644 index 0000000..eea8022 --- /dev/null +++ b/cadence/contracts/utility/FlowToken.cdc @@ -0,0 +1,311 @@ +import "FungibleToken" +import "MetadataViews" +import "FungibleTokenMetadataViews" +import "ViewResolver" + +access(all) contract FlowToken: ViewResolver { + + // Total supply of Flow tokens in existence + access(all) var totalSupply: UFix64 + + // Event that is emitted when the contract is created + access(all) event TokensInitialized(initialSupply: UFix64) + + // Event that is emitted when tokens are withdrawn from a Vault + access(all) event TokensWithdrawn(amount: UFix64, from: Address?) + + // Event that is emitted when tokens are deposited to a Vault + access(all) event TokensDeposited(amount: UFix64, to: Address?) + + // Event that is emitted when new tokens are minted + access(all) event TokensMinted(amount: UFix64) + + // Event that is emitted when tokens are destroyed + access(all) event TokensBurned(amount: UFix64) + + // Event that is emitted when a new minter resource is created + access(all) event MinterCreated(allowedAmount: UFix64) + + // Event that is emitted when a new burner resource is created + access(all) event BurnerCreated() + + // Vault + // + // Each user stores an instance of only the Vault in their storage + // The functions in the Vault and governed by the pre and post conditions + // in FungibleToken when they are called. + // The checks happen at runtime whenever a function is called. + // + // Resources can only be created in the context of the contract that they + // are defined in, so there is no way for a malicious user to create Vaults + // out of thin air. A special Minter resource needs to be defined to mint + // new tokens. + // + access(all) resource Vault: FungibleToken.Vault, FungibleToken.Provider, FungibleToken.Receiver, ViewResolver.Resolver { + + // holds the balance of a users tokens + access(all) var balance: UFix64 + + access(all) view fun getBalance(): UFix64 { + return self.balance + } + + // initialize the balance at resource creation time + init(balance: UFix64) { + self.balance = balance + } + + /// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts + access(all) view fun getSupportedVaultTypes(): {Type: Bool} { + return {self.getType(): true} + } + + access(all) view fun isSupportedVaultType(type: Type): Bool { + if (type == self.getType()) { return true } else { return false } + } + + /// Returns the storage path where the vault should typically be stored + access(all) view fun getDefaultStoragePath(): StoragePath? { + return /storage/flowTokenVault + } + + /// Returns the public path where this vault should have a public capability + access(all) view fun getDefaultPublicPath(): PublicPath? { + return /public/flowTokenReceiver + } + + // withdraw + // + // Function that takes an integer amount as an argument + // and withdraws that amount from the Vault. + // It creates a new temporary Vault that is used to hold + // the money that is being transferred. It returns the newly + // created Vault to the context that called so it can be deposited + // elsewhere. + // + access(FungibleToken.Withdrawable) fun withdraw(amount: UFix64): @{FungibleToken.Vault} { + self.balance = self.balance - amount + emit TokensWithdrawn(amount: amount, from: self.owner?.address) + return <-create Vault(balance: amount) + } + + // deposit + // + // Function that takes a Vault object as an argument and adds + // its balance to the balance of the owners Vault. + // It is allowed to destroy the sent Vault because the Vault + // was a temporary holder of the tokens. The Vault's balance has + // been consumed and therefore can be destroyed. + access(all) fun deposit(from: @{FungibleToken.Vault}) { + let vault <- from as! @FlowToken.Vault + self.balance = self.balance + vault.balance + emit TokensDeposited(amount: vault.balance, to: self.owner?.address) + vault.balance = 0.0 + destroy vault + } + + /// Get all the Metadata Views implemented by FlowToken + /// + /// @return An array of Types defining the implemented views. This value will be used by + /// developers to know which parameter to pass to the resolveView() method. + /// + access(all) view fun getViews(): [Type]{ + return FlowToken.getViews() + } + + /// Get a Metadata View from FlowToken + /// + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveView(_ view: Type): AnyStruct? { + return FlowToken.resolveView(view) + } + + access(all) fun createEmptyVault(): @{FungibleToken.Vault} { + return <-create Vault(balance: 0.0) + } + } + + // createEmptyVault + // + // Function that creates a new Vault with a balance of zero + // and returns it to the calling context. A user must call this function + // and store the returned Vault in their storage in order to allow their + // account to be able to receive deposits of this token type. + // + access(all) fun createEmptyVault(): @FlowToken.Vault { + return <-create Vault(balance: 0.0) + } + + access(all) view fun getViews(): [Type] { + return [Type(), + Type(), + Type(), + Type()] + } + + /// Get a Metadata View from FlowToken + /// + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveView(_ view: Type): AnyStruct? { + switch view { + case Type(): + return FungibleTokenMetadataViews.FTView( + ftDisplay: self.resolveView(Type()) as! FungibleTokenMetadataViews.FTDisplay?, + ftVaultData: self.resolveView(Type()) as! FungibleTokenMetadataViews.FTVaultData? + ) + case Type(): + let media = MetadataViews.Media( + file: MetadataViews.HTTPFile( + url: FlowToken.getLogoURI() + ), + mediaType: "image/svg+xml" + ) + let medias = MetadataViews.Medias([media]) + return FungibleTokenMetadataViews.FTDisplay( + name: "FLOW Network Token", + symbol: "FLOW", + description: "FLOW is the native token for the Flow blockchain. It is required for securing the network, transaction fees, storage fees, staking, FLIP voting and may be used by applications built on the Flow Blockchain", + externalURL: MetadataViews.ExternalURL("https://flow.com"), + logos: medias, + socials: { + "twitter": MetadataViews.ExternalURL("https://twitter.com/flow_blockchain") + } + ) + case Type(): + return FungibleTokenMetadataViews.FTVaultData( + storagePath: /storage/flowTokenVault, + receiverPath: /public/flowTokenReceiver, + metadataPath: /public/flowTokenBalance, + providerPath: /private/flowTokenVault, + receiverLinkedType: Type<&FlowToken.Vault>(), + metadataLinkedType: Type<&FlowToken.Vault>(), + providerLinkedType: Type<&FlowToken.Vault>(), + createEmptyVaultFunction: (fun (): @{FungibleToken.Vault} { + return <-FlowToken.createEmptyVault() + }) + ) + case Type(): + return FungibleTokenMetadataViews.TotalSupply(totalSupply: FlowToken.totalSupply) + } + return nil + } + + access(all) resource Administrator { + // createNewMinter + // + // Function that creates and returns a new minter resource + // + access(all) fun createNewMinter(allowedAmount: UFix64): @Minter { + emit MinterCreated(allowedAmount: allowedAmount) + return <-create Minter(allowedAmount: allowedAmount) + } + + // createNewBurner + // + // Function that creates and returns a new burner resource + // + access(all) fun createNewBurner(): @Burner { + emit BurnerCreated() + return <-create Burner() + } + } + + // Minter + // + // Resource object that token admin accounts can hold to mint new tokens. + // + access(all) resource Minter { + + // the amount of tokens that the minter is allowed to mint + access(all) var allowedAmount: UFix64 + + // mintTokens + // + // Function that mints new tokens, adds them to the total supply, + // and returns them to the calling context. + // + access(all) fun mintTokens(amount: UFix64): @FlowToken.Vault { + pre { + amount > UFix64(0): "Amount minted must be greater than zero" + amount <= self.allowedAmount: "Amount minted must be less than the allowed amount" + } + FlowToken.totalSupply = FlowToken.totalSupply + amount + self.allowedAmount = self.allowedAmount - amount + emit TokensMinted(amount: amount) + return <-create Vault(balance: amount) + } + + init(allowedAmount: UFix64) { + self.allowedAmount = allowedAmount + } + } + + // Burner + // + // Resource object that token admin accounts can hold to burn tokens. + // + access(all) resource Burner { + + // burnTokens + // + // Function that destroys a Vault instance, effectively burning the tokens. + // + // Note: the burned tokens are automatically subtracted from the + // total supply in the Vault destructor. + // + access(all) fun burnTokens(from: @FlowToken.Vault) { + FlowToken.burnTokens(from: <-from) + } + } + + access(all) fun burnTokens(from: @FlowToken.Vault) { + let vault <- from as! @FlowToken.Vault + let amount = vault.balance + destroy vault + if amount > 0.0 { + FlowToken.totalSupply = FlowToken.totalSupply - amount + emit TokensBurned(amount: amount) + } + } + + /// Gets the Flow Logo XML URI from storage + access(all) fun getLogoURI(): String { + return FlowToken.account.storage.copy(from: /storage/flowTokenLogoURI) ?? "" + } + + init(adminAccount: auth(Storage, Capabilities) &Account) { + self.totalSupply = 0.0 + + // Create the Vault with the total supply of tokens and save it in storage + // + let vault <- create Vault(balance: self.totalSupply) + + // Example of how to resolve a metadata view for a Vault + let ftView = vault.resolveView(Type()) + + adminAccount.storage.save(<-vault, to: /storage/flowTokenVault) + + // Create a public capability to the stored Vault that only exposes + // the `deposit` method through the `Receiver` interface + // + let receiverCapability = adminAccount.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault) + adminAccount.capabilities.publish(receiverCapability, at: /public/flowTokenReceiver) + + // Create a public capability to the stored Vault that only exposes + // the `balance` field through the `Balance` interface + // + let balanceCapability = adminAccount.capabilities.storage.issue<&FlowToken.Vault>(/storage/flowTokenVault) + adminAccount.capabilities.publish(balanceCapability, at: /public/flowTokenBalance) + + let admin <- create Administrator() + adminAccount.storage.save(<-admin, to: /storage/flowTokenAdmin) + + // Emit an event that shows that the contract was initialized + emit TokensInitialized(initialSupply: self.totalSupply) + + } +} diff --git a/cadence/contracts/utility/FungibleToken.cdc b/cadence/contracts/utility/FungibleToken.cdc new file mode 100644 index 0000000..f8d2e84 --- /dev/null +++ b/cadence/contracts/utility/FungibleToken.cdc @@ -0,0 +1,201 @@ +/** + +# The Flow Fungible Token standard + +## `FungibleToken` contract + +The Fungible Token standard is no longer an interface +that all fungible token contracts would have to conform to. + +If a users wants to deploy a new token contract, their contract +does not need to implement the FungibleToken interface, but their tokens +do need to implement the interfaces defined in this contract. + +## `Vault` resource interface + +Each fungible token resource type needs to implement the `Vault` resource interface. + +## `Provider`, `Receiver`, and `Balance` resource interfaces + +These interfaces declare pre-conditions and post-conditions that restrict +the execution of the functions in the Vault. + +They are separate because it gives the user the ability to share +a reference to their Vault that only exposes the fields functions +in one or more of the interfaces. + +It also gives users the ability to make custom resources that implement +these interfaces to do various things with the tokens. +For example, a faucet can be implemented by conforming +to the Provider interface. + +*/ + +import "ViewResolver" + +/// FungibleToken +/// +/// Fungible Token implementations are no longer required to implement the fungible token +/// interface. We still have it as an interface here because there are some useful +/// utility methods that many projects will still want to have on their contracts, +/// but they are by no means required. all that is required is that the token +/// implements the `Vault` interface +access(all) contract FungibleToken { + + // An entitlement for allowing the withdrawal of tokens from a Vault + access(all) entitlement Withdrawable + + /// The event that is emitted when tokens are withdrawn from a Vault + access(all) event Withdraw(amount: UFix64, from: Address?, type: String) + + /// The event that is emitted when tokens are deposited to a Vault + access(all) event Deposit(amount: UFix64, to: Address?, type: String) + + /// Provider + /// + /// The interface that enforces the requirements for withdrawing + /// tokens from the implementing type. + /// + /// It does not enforce requirements on `balance` here, + /// because it leaves open the possibility of creating custom providers + /// that do not necessarily need their own balance. + /// + access(all) resource interface Provider { + + /// withdraw subtracts tokens from the owner's Vault + /// and returns a Vault with the removed tokens. + /// + /// The function's access level is public, but this is not a problem + /// because only the owner storing the resource in their account + /// can initially call this function. + /// + /// The owner may grant other accounts access by creating a private + /// capability that allows specific other users to access + /// the provider resource through a reference. + /// + /// The owner may also grant all accounts access by creating a public + /// capability that allows all users to access the provider + /// resource through a reference. + /// + access(Withdrawable) fun withdraw(amount: UFix64): @{Vault} { + post { + // `result` refers to the return value + result.getBalance() == amount: + "Withdrawal amount must be the same as the balance of the withdrawn Vault" + emit Withdraw(amount: amount, from: self.owner?.address, type: self.getType().identifier) + } + } + } + + /// Receiver + /// + /// The interface that enforces the requirements for depositing + /// tokens into the implementing type. + /// + /// We do not include a condition that checks the balance because + /// we want to give users the ability to make custom receivers that + /// can do custom things with the tokens, like split them up and + /// send them to different places. + /// + access(all) resource interface Receiver { + + /// deposit takes a Vault and deposits it into the implementing resource type + /// + access(all) fun deposit(from: @{Vault}) + + /// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts + access(all) view fun getSupportedVaultTypes(): {Type: Bool} { + pre { true: "dummy" } + } + + /// Returns whether or not the given type is accepted by the Receiver + /// A vault that can accept any type should just return true by default + access(all) view fun isSupportedVaultType(type: Type): Bool { + pre { true: "dummy" } + } + } + + /// Vault + /// + /// Ideally, this interface would also conform to Receiver, Balance, Transferor, Provider, and Resolver + /// but that is not supported yet + /// + access(all) resource interface Vault: Receiver, Provider, ViewResolver.Resolver { + + //access(all) event ResourceDestroyed(balance: UFix64 = self.getBalance()) + + /// Get the balance of the vault + access(all) view fun getBalance(): UFix64 + + /// getSupportedVaultTypes optionally returns a list of vault types that this receiver accepts + access(all) view fun getSupportedVaultTypes(): {Type: Bool} { + // Below check is implemented to make sure that run-time type would + // only get returned when the parent resource conforms with `FungibleToken.Vault`. + if self.getType().isSubtype(of: Type<@{FungibleToken.Vault}>()) { + return {self.getType(): true} + } else { + // Return an empty dictionary as the default value for resource who don't + // implement `FungibleToken.Vault`, such as `FungibleTokenSwitchboard`, `TokenForwarder` etc. + return {} + } + } + + access(all) view fun isSupportedVaultType(type: Type): Bool { + return self.getSupportedVaultTypes()[type] ?? false + } + + /// Returns the storage path where the vault should typically be stored + access(all) view fun getDefaultStoragePath(): StoragePath? + + /// Returns the public path where this vault should have a public capability + access(all) view fun getDefaultPublicPath(): PublicPath? + + /// Returns the public path where this vault's Receiver should have a public capability + /// Publishing a Receiver Capability at a different path enables alternate Receiver implementations to be used + /// in the same canonical namespace as the underlying Vault. + access(all) view fun getDefaultReceiverPath(): PublicPath? { + return nil + } + + /// withdraw subtracts `amount` from the Vault's balance + /// and returns a new Vault with the subtracted balance + /// + access(Withdrawable) fun withdraw(amount: UFix64): @{Vault} { + pre { + self.getBalance() >= amount: + "Amount withdrawn must be less than or equal than the balance of the Vault" + } + post { + // use the special function `before` to get the value of the `balance` field + // at the beginning of the function execution + // + self.getBalance() == before(self.getBalance()) - amount: + "New Vault balance must be the difference of the previous balance and the withdrawn Vault balance" + } + } + + /// deposit takes a Vault and adds its balance to the balance of this Vault + /// + access(all) fun deposit(from: @{FungibleToken.Vault}) { + // Assert that the concrete type of the deposited vault is the same + // as the vault that is accepting the deposit + pre { + from.isInstance(self.getType()): + "Cannot deposit an incompatible token type" + emit Deposit(amount: from.getBalance(), to: self.owner?.address, type: from.getType().identifier) + } + post { + self.getBalance() == before(self.getBalance()) + before(from.getBalance()): + "New Vault balance must be the sum of the previous balance and the deposited Vault" + } + } + + /// createEmptyVault allows any user to create a new Vault that has a zero balance + /// + access(all) fun createEmptyVault(): @{Vault} { + post { + result.getBalance() == 0.0: "The newly created Vault must have zero balance" + } + } + } +} \ No newline at end of file diff --git a/cadence/contracts/utility/FungibleTokenMetadataViews.cdc b/cadence/contracts/utility/FungibleTokenMetadataViews.cdc new file mode 100644 index 0000000..c424258 --- /dev/null +++ b/cadence/contracts/utility/FungibleTokenMetadataViews.cdc @@ -0,0 +1,192 @@ +import FungibleToken from "FungibleToken" +import MetadataViews from "MetadataViews" +import ViewResolver from "ViewResolver" + +/// This contract implements the metadata standard proposed +/// in FLIP-1087. +/// +/// Ref: https://github.com/onflow/flips/blob/main/application/20220811-fungible-tokens-metadata.md +/// +/// Structs and resources can implement one or more +/// metadata types, called views. Each view type represents +/// a different kind of metadata. +/// +access(all) contract FungibleTokenMetadataViews { + + /// FTView wraps FTDisplay and FTVaultData, and is used to give a complete + /// picture of a Fungible Token. Most Fungible Token contracts should + /// implement this view. + /// + access(all) struct FTView { + access(all) let ftDisplay: FTDisplay? + access(all) let ftVaultData: FTVaultData? + view init( + ftDisplay: FTDisplay?, + ftVaultData: FTVaultData? + ) { + self.ftDisplay = ftDisplay + self.ftVaultData = ftVaultData + } + } + + /// Helper to get a FT view. + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A FTView struct + /// + access(all) fun getFTView(viewResolver: &{ViewResolver.Resolver}): FTView { + let maybeFTView = viewResolver.resolveView(Type()) + if let ftView = maybeFTView { + return ftView as! FTView + } + return FTView( + ftDisplay: self.getFTDisplay(viewResolver), + ftVaultData: self.getFTVaultData(viewResolver) + ) + } + + /// View to expose the information needed to showcase this FT. + /// This can be used by applications to give an overview and + /// graphics of the FT. + /// + access(all) struct FTDisplay { + /// The display name for this token. + /// + /// Example: "Flow" + /// + access(all) let name: String + + /// The abbreviated symbol for this token. + /// + /// Example: "FLOW" + access(all) let symbol: String + + /// A description the provides an overview of this token. + /// + /// Example: "The FLOW token is the native currency of the Flow network." + access(all) let description: String + + /// External link to a URL to view more information about the fungible token. + access(all) let externalURL: MetadataViews.ExternalURL + + /// One or more versions of the fungible token logo. + access(all) let logos: MetadataViews.Medias + + /// Social links to reach the fungible token's social homepages. + /// Possible keys may be "instagram", "twitter", "discord", etc. + access(all) let socials: {String: MetadataViews.ExternalURL} + + view init( + name: String, + symbol: String, + description: String, + externalURL: MetadataViews.ExternalURL, + logos: MetadataViews.Medias, + socials: {String: MetadataViews.ExternalURL} + ) { + self.name = name + self.symbol = symbol + self.description = description + self.externalURL = externalURL + self.logos = logos + self.socials = socials + } + } + + /// Helper to get FTDisplay in a way that will return a typed optional. + /// + /// @param viewResolver: A reference to the resolver resource + /// @return An optional FTDisplay struct + /// + access(all) fun getFTDisplay(_ viewResolver: &{ViewResolver.Resolver}): FTDisplay? { + if let maybeDisplayView = viewResolver.resolveView(Type()) { + if let displayView = maybeDisplayView as? FTDisplay { + return displayView + } + } + return nil + } + + /// View to expose the information needed store and interact with a FT vault. + /// This can be used by applications to setup a FT vault with proper + /// storage and public capabilities. + /// + access(all) struct FTVaultData { + /// Path in storage where this FT vault is recommended to be stored. + access(all) let storagePath: StoragePath + + /// Public path which must be linked to expose the public receiver capability. + access(all) let receiverPath: PublicPath + + /// Public path which must be linked to expose the balance and resolver public capabilities. + access(all) let metadataPath: PublicPath + + /// Private path which should be linked to expose the provider capability to withdraw funds + /// from the vault. + access(all) let providerPath: PrivatePath + + /// Type that should be linked at the `receiverPath`. This is a restricted type requiring + /// the `FungibleToken.Receiver` interface. + access(all) let receiverLinkedType: Type + + /// Type that should be linked at the `receiverPath`. This is a restricted type requiring + /// the `ViewResolver.Resolver` interfaces. + access(all) let metadataLinkedType: Type + + /// Type that should be linked at the aforementioned private path. This + /// is normally a restricted type with at a minimum the `FungibleToken.Provider` interface. + access(all) let providerLinkedType: Type + + /// Function that allows creation of an empty FT vault that is intended + /// to store the funds. + access(all) let createEmptyVault: fun(): @{FungibleToken.Vault} + + view init( + storagePath: StoragePath, + receiverPath: PublicPath, + metadataPath: PublicPath, + providerPath: PrivatePath, + receiverLinkedType: Type, + metadataLinkedType: Type, + providerLinkedType: Type, + createEmptyVaultFunction: fun(): @{FungibleToken.Vault} + ) { + pre { + receiverLinkedType.isSubtype(of: Type<&{FungibleToken.Receiver}>()): "Receiver public type must include FungibleToken.Receiver." + metadataLinkedType.isSubtype(of: Type<&{ViewResolver.Resolver}>()): "Metadata public type must include ViewResolver.Resolver interfaces." + providerLinkedType.isSubtype(of: Type<&{FungibleToken.Provider}>()): "Provider type must include FungibleToken.Provider interface." + } + self.storagePath = storagePath + self.receiverPath = receiverPath + self.metadataPath = metadataPath + self.providerPath = providerPath + self.receiverLinkedType = receiverLinkedType + self.metadataLinkedType = metadataLinkedType + self.providerLinkedType = providerLinkedType + self.createEmptyVault = createEmptyVaultFunction + } + } + + /// Helper to get FTVaultData in a way that will return a typed Optional. + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional FTVaultData struct + /// + access(all) fun getFTVaultData(_ viewResolver: &{ViewResolver.Resolver}): FTVaultData? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? FTVaultData { + return v + } + } + return nil + } + + /// View to expose the total supply of the Vault's token + access(all) struct TotalSupply { + access(all) let supply: UFix64 + + view init(totalSupply: UFix64) { + self.supply = totalSupply + } + } +} \ No newline at end of file diff --git a/cadence/contracts/utility/MetadataViews.cdc b/cadence/contracts/utility/MetadataViews.cdc new file mode 100644 index 0000000..8207326 --- /dev/null +++ b/cadence/contracts/utility/MetadataViews.cdc @@ -0,0 +1,722 @@ +import FungibleToken from "FungibleToken" +import NonFungibleToken from "NonFungibleToken" +import ViewResolver from "ViewResolver" + +/// This contract implements the metadata standard proposed +/// in FLIP-0636. +/// +/// Ref: https://github.com/onflow/flips/blob/main/application/20210916-nft-metadata.md +/// +/// Structs and resources can implement one or more +/// metadata types, called views. Each view type represents +/// a different kind of metadata, such as a creator biography +/// or a JPEG image file. +/// +access(all) contract MetadataViews { + + /// Display is a basic view that includes the name, description and + /// thumbnail for an object. Most objects should implement this view. + /// + access(all) struct Display { + + /// The name of the object. + /// + /// This field will be displayed in lists and therefore should + /// be short an concise. + /// + access(all) let name: String + + /// A written description of the object. + /// + /// This field will be displayed in a detailed view of the object, + /// so can be more verbose (e.g. a paragraph instead of a single line). + /// + access(all) let description: String + + /// A small thumbnail representation of the object. + /// + /// This field should be a web-friendly file (i.e JPEG, PNG) + /// that can be displayed in lists, link previews, etc. + /// + access(all) let thumbnail: {File} + + view init( + name: String, + description: String, + thumbnail: {File} + ) { + self.name = name + self.description = description + self.thumbnail = thumbnail + } + } + + /// Helper to get Display in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return An optional Display struct + /// + access(all) fun getDisplay(_ viewResolver: &{ViewResolver.Resolver}) : Display? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? Display { + return v + } + } + return nil + } + + /// Generic interface that represents a file stored on or off chain. Files + /// can be used to references images, videos and other media. + /// + access(all) struct interface File { + access(all) view fun uri(): String + } + + /// View to expose a file that is accessible at an HTTP (or HTTPS) URL. + /// + access(all) struct HTTPFile: File { + access(all) let url: String + + view init(url: String) { + self.url = url + } + + access(all) view fun uri(): String { + return self.url + } + } + + /// View to expose a file stored on IPFS. + /// IPFS images are referenced by their content identifier (CID) + /// rather than a direct URI. A client application can use this CID + /// to find and load the image via an IPFS gateway. + /// + access(all) struct IPFSFile: File { + + /// CID is the content identifier for this IPFS file. + /// + /// Ref: https://docs.ipfs.io/concepts/content-addressing/ + /// + access(all) let cid: String + + /// Path is an optional path to the file resource in an IPFS directory. + /// + /// This field is only needed if the file is inside a directory. + /// + /// Ref: https://docs.ipfs.io/concepts/file-systems/ + /// + access(all) let path: String? + + view init(cid: String, path: String?) { + self.cid = cid + self.path = path + } + + /// This function returns the IPFS native URL for this file. + /// Ref: https://docs.ipfs.io/how-to/address-ipfs-on-web/#native-urls + /// + /// @return The string containing the file uri + /// + access(all) view fun uri(): String { + if let path = self.path { + return "ipfs://".concat(self.cid).concat("/").concat(path) + } + + return "ipfs://".concat(self.cid) + } + } + + /// View to represent a file with an correspoiding mediaType. + /// + access(all) struct Media { + + /// File for the media + /// + access(all) let file: {File} + + /// media-type comes on the form of type/subtype as described here + /// https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types + /// + access(all) let mediaType: String + + view init(file: {File}, mediaType: String) { + self.file=file + self.mediaType=mediaType + } + } + + /// Wrapper view for multiple media views + /// + access(all) struct Medias { + + /// An arbitrary-sized list for any number of Media items + access(all) let items: [Media] + + view init(_ items: [Media]) { + self.items = items + } + } + + /// Helper to get Medias in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional Medias struct + /// + access(all) fun getMedias(_ viewResolver: &{ViewResolver.Resolver}) : Medias? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? Medias { + return v + } + } + return nil + } + + /// View to represent a license according to https://spdx.org/licenses/ + /// This view can be used if the content of an NFT is licensed. + /// + access(all) struct License { + access(all) let spdxIdentifier: String + + view init(_ identifier: String) { + self.spdxIdentifier = identifier + } + } + + /// Helper to get License in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional License struct + /// + access(all) fun getLicense(_ viewResolver: &{ViewResolver.Resolver}) : License? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? License { + return v + } + } + return nil + } + + /// View to expose a URL to this item on an external site. + /// This can be used by applications like .find and Blocto to direct users + /// to the original link for an NFT or a project page that describes the NFT collection. + /// eg https://www.my-nft-project.com/overview-of-nft-collection + /// + access(all) struct ExternalURL { + access(all) let url: String + + view init(_ url: String) { + self.url=url + } + } + + /// Helper to get ExternalURL in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional ExternalURL struct + /// + access(all) fun getExternalURL(_ viewResolver: &{ViewResolver.Resolver}) : ExternalURL? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? ExternalURL { + return v + } + } + return nil + } + + /// View that defines the composable royalty standard that gives marketplaces a + /// unified interface to support NFT royalties. + /// + access(all) struct Royalty { + + /// Generic FungibleToken Receiver for the beneficiary of the royalty + /// Can get the concrete type of the receiver with receiver.getType() + /// Recommendation - Users should create a new link for a FlowToken + /// receiver for this using `getRoyaltyReceiverPublicPath()`, and not + /// use the default FlowToken receiver. This will allow users to update + /// the capability in the future to use a more generic capability + access(all) let receiver: Capability<&{FungibleToken.Receiver}> + + /// Multiplier used to calculate the amount of sale value transferred to + /// royalty receiver. Note - It should be between 0.0 and 1.0 + /// Ex - If the sale value is x and multiplier is 0.56 then the royalty + /// value would be 0.56 * x. + /// Generally percentage get represented in terms of basis points + /// in solidity based smart contracts while cadence offers `UFix64` + /// that already supports the basis points use case because its + /// operations are entirely deterministic integer operations and support + /// up to 8 points of precision. + access(all) let cut: UFix64 + + /// Optional description: This can be the cause of paying the royalty, + /// the relationship between the `wallet` and the NFT, or anything else + /// that the owner might want to specify. + access(all) let description: String + + view init(receiver: Capability<&{FungibleToken.Receiver}>, cut: UFix64, description: String) { + pre { + cut >= 0.0 && cut <= 1.0 : "Cut value should be in valid range i.e [0,1]" + } + self.receiver = receiver + self.cut = cut + self.description = description + } + } + + /// Wrapper view for multiple Royalty views. + /// Marketplaces can query this `Royalties` struct from NFTs + /// and are expected to pay royalties based on these specifications. + /// + access(all) struct Royalties { + + /// Array that tracks the individual royalties + access(self) let cutInfos: [Royalty] + + access(all) view init(_ cutInfos: [Royalty]) { + // Validate that sum of all cut multipliers should not be greater than 1.0 + var totalCut = 0.0 + for royalty in cutInfos { + totalCut = totalCut + royalty.cut + } + assert(totalCut <= 1.0, message: "Sum of cutInfos multipliers should not be greater than 1.0") + // Assign the cutInfos + self.cutInfos = cutInfos + } + + /// Return the cutInfos list + /// + /// @return An array containing all the royalties structs + /// + access(all) view fun getRoyalties(): [Royalty] { + return self.cutInfos + } + } + + /// Helper to get Royalties in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional Royalties struct + /// + access(all) fun getRoyalties(_ viewResolver: &{ViewResolver.Resolver}) : Royalties? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? Royalties { + return v + } + } + return nil + } + + /// Get the path that should be used for receiving royalties + /// This is a path that will eventually be used for a generic switchboard receiver, + /// hence the name but will only be used for royalties for now. + /// + /// @return The PublicPath for the generic FT receiver + /// + access(all) view fun getRoyaltyReceiverPublicPath(): PublicPath { + return /public/GenericFTReceiver + } + + /// View to represent a single field of metadata on an NFT. + /// This is used to get traits of individual key/value pairs along with some + /// contextualized data about the trait + /// + access(all) struct Trait { + // The name of the trait. Like Background, Eyes, Hair, etc. + access(all) let name: String + + // The underlying value of the trait, the rest of the fields of a trait provide context to the value. + access(all) let value: AnyStruct + + // displayType is used to show some context about what this name and value represent + // for instance, you could set value to a unix timestamp, and specify displayType as "Date" to tell + // platforms to consume this trait as a date and not a number + access(all) let displayType: String? + + // Rarity can also be used directly on an attribute. + // + // This is optional because not all attributes need to contribute to the NFT's rarity. + access(all) let rarity: Rarity? + + view init(name: String, value: AnyStruct, displayType: String?, rarity: Rarity?) { + self.name = name + self.value = value + self.displayType = displayType + self.rarity = rarity + } + } + + /// Wrapper view to return all the traits on an NFT. + /// This is used to return traits as individual key/value pairs along with + /// some contextualized data about each trait. + access(all) struct Traits { + access(all) let traits: [Trait] + + view init(_ traits: [Trait]) { + self.traits = traits + } + + /// Adds a single Trait to the Traits view + /// + /// @param Trait: The trait struct to be added + /// + access(all) fun addTrait(_ t: Trait) { + self.traits.append(t) + } + } + + /// Helper to get Traits view in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional Traits struct + /// + access(all) fun getTraits(_ viewResolver: &{ViewResolver.Resolver}) : Traits? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? Traits { + return v + } + } + return nil + } + + /// Helper function to easily convert a dictionary to traits. For NFT + /// collections that do not need either of the optional values of a Trait, + /// this method should suffice to give them an array of valid traits. + /// + /// @param dict: The dictionary to be converted to Traits + /// @param excludedNames: An optional String array specifying the `dict` + /// keys that are not wanted to become `Traits` + /// @return The generated Traits view + /// + access(all) fun dictToTraits(dict: {String: AnyStruct}, excludedNames: [String]?): Traits { + // Collection owners might not want all the fields in their metadata included. + // They might want to handle some specially, or they might just not want them included at all. + if excludedNames != nil { + for k in excludedNames! { + dict.remove(key: k) + } + } + + let traits: [Trait] = [] + for k in dict.keys { + let trait = Trait(name: k, value: dict[k]!, displayType: nil, rarity: nil) + traits.append(trait) + } + + return Traits(traits) + } + + /// Optional view for collections that issue multiple objects + /// with the same or similar metadata, for example an X of 100 set. This + /// information is useful for wallets and marketplaces. + /// An NFT might be part of multiple editions, which is why the edition + /// information is returned as an arbitrary sized array + /// + access(all) struct Edition { + + /// The name of the edition + /// For example, this could be Set, Play, Series, + /// or any other way a project could classify its editions + access(all) let name: String? + + /// The edition number of the object. + /// For an "24 of 100 (#24/100)" item, the number is 24. + access(all) let number: UInt64 + + /// The max edition number of this type of objects. + /// This field should only be provided for limited-editioned objects. + /// For an "24 of 100 (#24/100)" item, max is 100. + /// For an item with unlimited edition, max should be set to nil. + /// + access(all) let max: UInt64? + + view init(name: String?, number: UInt64, max: UInt64?) { + if max != nil { + assert(number <= max!, message: "The number cannot be greater than the max number!") + } + self.name = name + self.number = number + self.max = max + } + } + + /// Wrapper view for multiple Edition views + /// + access(all) struct Editions { + + /// An arbitrary-sized list for any number of editions + /// that the NFT might be a part of + access(all) let infoList: [Edition] + + view init(_ infoList: [Edition]) { + self.infoList = infoList + } + } + + /// Helper to get Editions in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return An optional Editions struct + /// + access(all) fun getEditions(_ viewResolver: &{ViewResolver.Resolver}) : Editions? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? Editions { + return v + } + } + return nil + } + + /// View representing a project-defined serial number for a specific NFT + /// Projects have different definitions for what a serial number should be + /// Some may use the NFTs regular ID and some may use a different + /// classification system. The serial number is expected to be unique among + /// other NFTs within that project + /// + access(all) struct Serial { + access(all) let number: UInt64 + + view init(_ number: UInt64) { + self.number = number + } + } + + /// Helper to get Serial in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return An optional Serial struct + /// + access(all) fun getSerial(_ viewResolver: &{ViewResolver.Resolver}) : Serial? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? Serial { + return v + } + } + return nil + } + + /// View to expose rarity information for a single rarity + /// Note that a rarity needs to have either score or description but it can + /// have both + /// + access(all) struct Rarity { + /// The score of the rarity as a number + access(all) let score: UFix64? + + /// The maximum value of score + access(all) let max: UFix64? + + /// The description of the rarity as a string. + /// + /// This could be Legendary, Epic, Rare, Uncommon, Common or any other string value + access(all) let description: String? + + view init(score: UFix64?, max: UFix64?, description: String?) { + if score == nil && description == nil { + panic("A Rarity needs to set score, description or both") + } + + self.score = score + self.max = max + self.description = description + } + } + + /// Helper to get Rarity view in a typesafe way + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional Rarity struct + /// + access(all) fun getRarity(_ viewResolver: &{ViewResolver.Resolver}) : Rarity? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? Rarity { + return v + } + } + return nil + } + + /// NFTView wraps all Core views along `id` and `uuid` fields, and is used + /// to give a complete picture of an NFT. Most NFTs should implement this + /// view. + /// + access(all) struct NFTView { + access(all) let id: UInt64 + access(all) let uuid: UInt64 + access(all) let display: MetadataViews.Display? + access(all) let externalURL: MetadataViews.ExternalURL? + access(all) let collectionData: NFTCollectionData? + access(all) let collectionDisplay: NFTCollectionDisplay? + access(all) let royalties: Royalties? + access(all) let traits: Traits? + + view init( + id : UInt64, + uuid : UInt64, + display : MetadataViews.Display?, + externalURL : MetadataViews.ExternalURL?, + collectionData : NFTCollectionData?, + collectionDisplay : NFTCollectionDisplay?, + royalties : Royalties?, + traits: Traits? + ) { + self.id = id + self.uuid = uuid + self.display = display + self.externalURL = externalURL + self.collectionData = collectionData + self.collectionDisplay = collectionDisplay + self.royalties = royalties + self.traits = traits + } + } + + /// Helper to get an NFT view + /// + /// @param id: The NFT id + /// @param viewResolver: A reference to the resolver resource + /// @return A NFTView struct + /// + access(all) fun getNFTView(id: UInt64, viewResolver: &{ViewResolver.Resolver}) : NFTView { + let nftView = viewResolver.resolveView(Type()) + if nftView != nil { + return nftView! as! NFTView + } + + return NFTView( + id : id, + uuid: viewResolver.uuid, + display: MetadataViews.getDisplay(viewResolver), + externalURL : MetadataViews.getExternalURL(viewResolver), + collectionData : self.getNFTCollectionData(viewResolver), + collectionDisplay : self.getNFTCollectionDisplay(viewResolver), + royalties : self.getRoyalties(viewResolver), + traits : self.getTraits(viewResolver) + ) + } + + /// View to expose the information needed store and retrieve an NFT. + /// This can be used by applications to setup a NFT collection with proper + /// storage and public capabilities. + /// + access(all) struct NFTCollectionData { + /// Path in storage where this NFT is recommended to be stored. + access(all) let storagePath: StoragePath + + /// Public path which must be linked to expose public capabilities of this NFT + /// including standard NFT interfaces and metadataviews interfaces + access(all) let publicPath: PublicPath + + /// Private path which should be linked to expose the provider + /// capability to withdraw NFTs from the collection holding NFTs + access(all) let providerPath: PrivatePath + + /// Public collection type that is expected to provide sufficient read-only access to standard + /// functions (deposit + getIDs + borrowNFT). For new + /// collections, this may be set to be equal to the type specified in `publicLinkedType`. + access(all) let publicCollection: Type + + /// Type that should be linked at the aforementioned public path. This is normally a + /// restricted type with many interfaces. Notably the + /// `NFT.Receiver`, and `ViewResolver.ResolverCollection` interfaces are required. + access(all) let publicLinkedType: Type + + /// Type that should be linked at the aforementioned private path. This is normally + /// a restricted type with at a minimum the `NFT.Provider` interface + access(all) let providerLinkedType: Type + + /// Function that allows creation of an empty NFT collection that is intended to store + /// this NFT. + access(all) let createEmptyCollection: fun(): @{NonFungibleToken.Collection} + + view init( + storagePath: StoragePath, + publicPath: PublicPath, + providerPath: PrivatePath, + publicCollection: Type, + publicLinkedType: Type, + providerLinkedType: Type, + createEmptyCollectionFunction: fun(): @{NonFungibleToken.Collection} + ) { + pre { + publicLinkedType.isSubtype(of: Type<&{NonFungibleToken.Receiver, ViewResolver.ResolverCollection}>()): "Public type must include NonFungibleToken.Receiver and ViewResolver.ResolverCollection interfaces." + providerLinkedType.isSubtype(of: Type<&{NonFungibleToken.Provider, ViewResolver.ResolverCollection}>()): "Provider type must include NonFungibleToken.Provider and ViewResolver.ResolverCollection interface." + } + self.storagePath=storagePath + self.publicPath=publicPath + self.providerPath = providerPath + self.publicCollection=publicCollection + self.publicLinkedType=publicLinkedType + self.providerLinkedType = providerLinkedType + self.createEmptyCollection=createEmptyCollectionFunction + } + } + + /// Helper to get NFTCollectionData in a way that will return an typed Optional + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional NFTCollectionData struct + /// + access(all) fun getNFTCollectionData(_ viewResolver: &{ViewResolver.Resolver}) : NFTCollectionData? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? NFTCollectionData { + return v + } + } + return nil + } + + /// View to expose the information needed to showcase this NFT's + /// collection. This can be used by applications to give an overview and + /// graphics of the NFT collection this NFT belongs to. + /// + access(all) struct NFTCollectionDisplay { + // Name that should be used when displaying this NFT collection. + access(all) let name: String + + // Description that should be used to give an overview of this collection. + access(all) let description: String + + // External link to a URL to view more information about this collection. + access(all) let externalURL: MetadataViews.ExternalURL + + // Square-sized image to represent this collection. + access(all) let squareImage: MetadataViews.Media + + // Banner-sized image for this collection, recommended to have a size near 1200x630. + access(all) let bannerImage: MetadataViews.Media + + // Social links to reach this collection's social homepages. + // Possible keys may be "instagram", "twitter", "discord", etc. + access(all) let socials: {String: MetadataViews.ExternalURL} + + view init( + name: String, + description: String, + externalURL: MetadataViews.ExternalURL, + squareImage: MetadataViews.Media, + bannerImage: MetadataViews.Media, + socials: {String: MetadataViews.ExternalURL} + ) { + self.name = name + self.description = description + self.externalURL = externalURL + self.squareImage = squareImage + self.bannerImage = bannerImage + self.socials = socials + } + } + + /// Helper to get NFTCollectionDisplay in a way that will return a typed + /// Optional + /// + /// @param viewResolver: A reference to the resolver resource + /// @return A optional NFTCollection struct + /// + access(all) fun getNFTCollectionDisplay(_ viewResolver: &{ViewResolver.Resolver}) : NFTCollectionDisplay? { + if let view = viewResolver.resolveView(Type()) { + if let v = view as? NFTCollectionDisplay { + return v + } + } + return nil + } +} diff --git a/cadence/contracts/utility/NonFungibleToken.cdc b/cadence/contracts/utility/NonFungibleToken.cdc new file mode 100644 index 0000000..3c92e0f --- /dev/null +++ b/cadence/contracts/utility/NonFungibleToken.cdc @@ -0,0 +1,191 @@ +/** + +## The Flow Non-Fungible Token standard + +## `NonFungibleToken` contract interface + +The interface that all Non-Fungible Token contracts should conform to. +If a user wants to deploy a new NFT contract, their contract would need +to implement the NonFungibleToken interface. + +Their contract must follow all the rules and naming +that the interface specifies. + +## `NFT` resource + +The core resource type that represents an NFT in the smart contract. + +## `Collection` Resource + +The resource that stores a user's NFT collection. +It includes a few functions to allow the owner to easily +move tokens in and out of the collection. + +## `Provider` and `Receiver` resource interfaces + +These interfaces declare functions with some pre and post conditions +that require the Collection to follow certain naming and behavior standards. + +They are separate because it gives the user the ability to share a reference +to their Collection that only exposes the fields and functions in one or more +of the interfaces. It also gives users the ability to make custom resources +that implement these interfaces to do various things with the tokens. + +By using resources and interfaces, users of NFT smart contracts can send +and receive tokens peer-to-peer, without having to interact with a central ledger +smart contract. + +To send an NFT to another user, a user would simply withdraw the NFT +from their Collection, then call the deposit function on another user's +Collection to complete the transfer. + +*/ + +import "ViewResolver" + +/// The main NFT contract interface. Other NFT contracts will +/// import and implement this interface +/// +access(all) contract NonFungibleToken { + + /// An entitlement for allowing the withdrawal of tokens from a Vault + access(all) entitlement Withdrawable + + /// An entitlement for allowing updates and update events for an NFT + access(all) entitlement Updatable + + /// Event that contracts should emit when the metadata of an NFT is updated + /// It can only be emitted by calling the `emitNFTUpdated` function + /// with an `Updatable` entitled reference to the NFT that was updated + /// The entitlement prevents spammers from calling this from other users' collections + /// because only code within a collection or that has special entitled access + /// to the collections methods will be able to get the entitled reference + /// + /// The event makes it so that third-party indexers can monitor the events + /// and query the updated metadata from the owners' collections. + /// + access(all) event Updated(id: UInt64, uuid: UInt64, owner: Address?, type: String) + access(all) view fun emitNFTUpdated(_ nftRef: auth(Updatable) &{NonFungibleToken.NFT}) + { + emit Updated(id: nftRef.getID(), uuid: nftRef.uuid, owner: nftRef.owner?.address, type: nftRef.getType().identifier) + } + + + /// Event that is emitted when a token is withdrawn, + /// indicating the owner of the collection that it was withdrawn from. + /// + /// If the collection is not in an account's storage, `from` will be `nil`. + /// + access(all) event Withdraw(id: UInt64, uuid: UInt64, from: Address?, type: String) + + /// Event that emitted when a token is deposited to a collection. + /// + /// It indicates the owner of the collection that it was deposited to. + /// + access(all) event Deposit(id: UInt64, uuid: UInt64, to: Address?, type: String) + + /// Interface that the NFTs must conform to + /// + access(all) resource interface NFT: ViewResolver.Resolver { + /// The unique ID that each NFT has + access(all) view fun getID(): UInt64 + + // access(all) event ResourceDestroyed(uuid: UInt64 = self.uuid, type: self.getType().identifier) + + /// Get a reference to an NFT that this NFT owns + /// Both arguments are optional to allow the NFT to choose + /// how it returns sub NFTs depending on what arguments are provided + /// For example, if `type` has a value, but `id` doesn't, the NFT + /// can choose which NFT of that type to return if there is a "default" + /// If both are `nil`, then NFTs that only store a single NFT can just return + /// that. This helps callers who aren't sure what they are looking for + /// + /// @param type: The Type of the desired NFT + /// @param id: The id of the NFT to borrow + /// + /// @return A structure representing the requested view. + access(all) fun getSubNFT(type: Type, id: UInt64) : &{NonFungibleToken.NFT}? { + return nil + } + } + + /// Interface to mediate withdraws from the Collection + /// + access(all) resource interface Provider { + + // We emit withdraw events from the provider interface because conficting withdraw + // events aren't as confusing to event listeners as conflicting deposit events + + /// withdraw removes an NFT from the collection and moves it to the caller + /// It does not specify whether the ID is UUID or not + access(Withdrawable) fun withdraw(withdrawID: UInt64): @{NFT} { + post { + result.getID() == withdrawID: "The ID of the withdrawn token must be the same as the requested ID" + emit Withdraw(id: result.getID(), uuid: result.uuid, from: self.owner?.address, type: result.getType().identifier) + } + } + } + + /// Interface to mediate deposits to the Collection + /// + access(all) resource interface Receiver { + + /// deposit takes an NFT as an argument and adds it to the Collection + /// + access(all) fun deposit(token: @{NFT}) + + /// getSupportedNFTTypes returns a list of NFT types that this receiver accepts + access(all) view fun getSupportedNFTTypes(): {Type: Bool} + + /// Returns whether or not the given type is accepted by the collection + /// A collection that can accept any type should just return true by default + access(all) view fun isSupportedNFTType(type: Type): Bool + } + + /// Requirement for the concrete resource type + /// to be declared in the implementing contract + /// + access(all) resource interface Collection: Provider, Receiver, ViewResolver.ResolverCollection { + + /// Return the default storage path for the collection + access(all) view fun getDefaultStoragePath(): StoragePath? + + /// Return the default public path for the collection + access(all) view fun getDefaultPublicPath(): PublicPath? + + /// Normally we would require that the collection specify + /// a specific dictionary to store the NFTs, but this isn't necessary any more + /// as long as all the other functions are there + + /// createEmptyCollection creates an empty Collection + /// and returns it to the caller so that they can own NFTs + access(all) fun createEmptyCollection(): @{Collection} { + post { + result.getLength() == 0: "The created collection must be empty!" + } + } + + /// deposit takes a NFT and adds it to the collections dictionary + /// and adds the ID to the id array + access(all) fun deposit(token: @{NonFungibleToken.NFT}) { + pre { + // We emit the deposit event in the `Collection` interface + // because the `Collection` interface is almost always the final destination + // of tokens and deposit emissions from custom receivers could be confusing + // and hard to reconcile to event listeners + emit Deposit(id: token.getID(), uuid: token.uuid, to: self.owner?.address, type: token.getType().identifier) + } + } + + /// Gets the amount of NFTs stored in the collection + access(all) view fun getLength(): Int + + access(all) view fun borrowNFT(_ id: UInt64): &{NonFungibleToken.NFT}? { + post { + (result == nil) || (result?.getID() == id): + "Cannot borrow NFT reference: The ID of the returned reference does not match the ID that was specified" + } + return nil + } + } +} diff --git a/cadence/contracts/utility/ViewResolver.cdc b/cadence/contracts/utility/ViewResolver.cdc new file mode 100644 index 0000000..6dd962f --- /dev/null +++ b/cadence/contracts/utility/ViewResolver.cdc @@ -0,0 +1,55 @@ +// Taken from the NFT Metadata standard, this contract exposes an interface to let +// anyone borrow a contract and resolve views on it. +// +// This will allow you to obtain information about a contract without necessarily knowing anything about it. +// All you need is its address and name and you're good to go! +access(all) contract interface ViewResolver { + + /// Function that returns all the Metadata Views implemented by the resolving contract + /// + /// @return An array of Types defining the implemented views. This value will be used by + /// developers to know which parameter to pass to the resolveView() method. + /// + access(all) view fun getViews(): [Type] { + return [] + } + + /// Function that resolves a metadata view for this token. + /// + /// @param view: The Type of the desired view. + /// @return A structure representing the requested view. + /// + access(all) fun resolveView(_ view: Type): AnyStruct? { + return nil + } + + /// Provides access to a set of metadata views. A struct or + /// resource (e.g. an NFT) can implement this interface to provide access to + /// the views that it supports. + /// + access(all) resource interface Resolver { + + /// Same as getViews above, but on a specific NFT instead of a contract + access(all) view fun getViews(): [Type] { + return [] + } + + /// Same as resolveView above, but on a specific NFT instead of a contract + access(all) fun resolveView(_ view: Type): AnyStruct? { + return nil + } + } + + /// A group of view resolvers indexed by ID. + /// + access(all) resource interface ResolverCollection { + access(all) view fun borrowViewResolver(id: UInt64): &{Resolver}? { + return nil + } + + access(all) view fun getIDs(): [UInt64] { + return [] + } + } +} + \ No newline at end of file diff --git a/cadence/scripts/checkFUSDVault.cdc b/cadence/scripts/checkFUSDVault.cdc deleted file mode 100644 index e00730c..0000000 --- a/cadence/scripts/checkFUSDVault.cdc +++ /dev/null @@ -1,12 +0,0 @@ -import FUSD from 0xFUSDADDRESS -import FungibleToken from 0xFUNGIBLETOKENADDRESS - -pub fun main(address: Address): Bool { - let receiver = getAccount(address) - .getCapability<&FUSD.Vault{FungibleToken.Receiver}>(/public/fusdReceiver) - .check() - let balance = getAccount(address) - .getCapability<&FUSD.Vault{FungibleToken.Balance}>(/public/fusdBalance) - .check() - return receiver && balance -} diff --git a/cadence/scripts/getAccount.cdc b/cadence/scripts/getAccount.cdc index 6cae595..aa2c3f1 100644 --- a/cadence/scripts/getAccount.cdc +++ b/cadence/scripts/getAccount.cdc @@ -1,3 +1,3 @@ -pub fun main(address: Address): PublicAccount { +access(all) fun main(address: Address): &Account { return getAccount(address) } diff --git a/cadence/scripts/getAccounts.cdc b/cadence/scripts/getAccounts.cdc index 5e5e1af..fdc3378 100644 --- a/cadence/scripts/getAccounts.cdc +++ b/cadence/scripts/getAccounts.cdc @@ -1,5 +1,5 @@ -import FCL from 0xSERVICE +import "FCL" -pub fun main(): [FCL.Account] { +access(all) fun main(): &[FCL.FCLAccount] { return FCL.accounts().values } diff --git a/cadence/scripts/getFUSDBalance.cdc b/cadence/scripts/getFUSDBalance.cdc deleted file mode 100644 index 99778a9..0000000 --- a/cadence/scripts/getFUSDBalance.cdc +++ /dev/null @@ -1,7 +0,0 @@ -import FungibleToken from 0xFUNGIBLETOKENADDRESS - -pub fun main(addr: Address): UFix64 { - return getAccount(addr) - .getCapability<&{FungibleToken.Balance}>(/public/fusdBalance) - .borrow()?.balance ?? 0.0 -} diff --git a/cadence/transactions/fundFLOW.cdc b/cadence/transactions/fundFLOW.cdc index caaae92..c94bd71 100644 --- a/cadence/transactions/fundFLOW.cdc +++ b/cadence/transactions/fundFLOW.cdc @@ -1,18 +1,20 @@ -import FlowToken from 0xFLOWTOKENADDRESS -import FungibleToken from 0xFUNGIBLETOKENADDRESS +import "FlowToken" +import "FungibleToken" transaction(address: Address, amount: UFix64) { let tokenAdmin: &FlowToken.Administrator let tokenReceiver: &{FungibleToken.Receiver} - prepare(signer: AuthAccount) { + prepare(signer: auth(Storage, Capabilities) &Account) { self.tokenAdmin = signer + .storage .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin) ?? panic("Signer is not the token admin") self.tokenReceiver = getAccount(address) - .getCapability(/public/flowTokenReceiver)! - .borrow<&{FungibleToken.Receiver}>() + .capabilities + .get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)! + .borrow() ?? panic("Unable to borrow receiver reference") } diff --git a/cadence/transactions/fundFUSD.cdc b/cadence/transactions/fundFUSD.cdc deleted file mode 100644 index 3c7ddaa..0000000 --- a/cadence/transactions/fundFUSD.cdc +++ /dev/null @@ -1,52 +0,0 @@ -import FUSD from 0xFUSDADDRESS -import FungibleToken from 0xFUNGIBLETOKENADDRESS - -pub fun hasFUSD(_ address: Address): Bool { - let receiver = getAccount(address) - .getCapability<&FUSD.Vault{FungibleToken.Receiver}>(/public/fusdReceiver) - .check() - - let balance = getAccount(address) - .getCapability<&FUSD.Vault{FungibleToken.Balance}>(/public/fusdBalance) - .check() - - return receiver && balance -} - -pub fun initFUSD(_ acct: AuthAccount) { - if acct.borrow<&FUSD.Vault>(from: /storage/fusdVault) == nil { - acct.save(<-FUSD.createEmptyVault(), to: /storage/fusdVault) - } - acct.unlink(/public/fusdReceiver) - acct.unlink(/public/fusdBalance) - acct.link<&FUSD.Vault{FungibleToken.Receiver}>(/public/fusdReceiver, target: /storage/fusdVault) - acct.link<&FUSD.Vault{FungibleToken.Balance}>(/public/fusdBalance, target: /storage/fusdVault) -} - -transaction(address: Address, amount: UFix64) { - let tokenAdmin: &FUSD.Administrator - let tokenReceiver: &{FungibleToken.Receiver} - - prepare(minterAccount: AuthAccount, receiverAccount: AuthAccount) { - if !hasFUSD(receiverAccount.address) { - initFUSD(receiverAccount) - } - - self.tokenAdmin = minterAccount - .borrow<&FUSD.Administrator>(from: FUSD.AdminStoragePath) - ?? panic("minterAccount is not the token admin") - - self.tokenReceiver = getAccount(address) - .getCapability(/public/fusdReceiver)! - .borrow<&{FungibleToken.Receiver}>() - ?? panic("Unable to borrow receiver reference") - } - - execute { - let minter <- self.tokenAdmin.createNewMinter() - let mintedVault <- minter.mintTokens(amount: amount) - - self.tokenReceiver.deposit(from: <-mintedVault) - destroy minter - } -} diff --git a/cadence/transactions/init.cdc b/cadence/transactions/init.cdc index 33bce21..d344b02 100644 --- a/cadence/transactions/init.cdc +++ b/cadence/transactions/init.cdc @@ -1,5 +1,5 @@ -transaction(code: String, key: String, initAccountsLabels: [String]) { - prepare(acct: AuthAccount) { - acct.contracts.add(name: "FCL", code: code.utf8, key: key, initAccountsLabels: initAccountsLabels) +transaction(code: String, publicKey: String, hashAlgorithm: UInt8, signAlgorithm: UInt8, initAccountsLabels: [String]) { + prepare(acct: auth(Contracts) &Account) { + acct.contracts.add(name: "FCL", code: code.utf8, publicKey: publicKey, hashAlgorithm: hashAlgorithm, signAlgorithm: signAlgorithm, initAccountsLabels: initAccountsLabels) } } diff --git a/cadence/transactions/newAccount.cdc b/cadence/transactions/newAccount.cdc index 21a061f..064932e 100644 --- a/cadence/transactions/newAccount.cdc +++ b/cadence/transactions/newAccount.cdc @@ -1,6 +1,6 @@ -import FCL from 0xSERVICE -import FlowToken from 0xFLOWTOKENADDRESS -import FungibleToken from 0xFUNGIBLETOKENADDRESS +import "FCL" +import "FlowToken" +import "FungibleToken" /// This transaction creates a new account and funds it with /// an initial balance of FLOW tokens. @@ -10,16 +10,18 @@ transaction(label: String, scopes: [String], initialBalance: UFix64) { let tokenAdmin: &FlowToken.Administrator let tokenReceiver: &{FungibleToken.Receiver} - prepare(signer: AuthAccount) { + prepare(signer: auth(Storage) &Account) { let account = FCL.new(label: label, scopes: scopes, address: nil) self.tokenAdmin = signer + .storage .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin) ?? panic("Signer is not the token admin") self.tokenReceiver = account - .getCapability(/public/flowTokenReceiver)! - .borrow<&{FungibleToken.Receiver}>() + .capabilities + .get<&{FungibleToken.Receiver}>(/public/flowTokenReceiver)! + .borrow() ?? panic("Unable to borrow receiver reference") } diff --git a/cadence/transactions/updateAccount.cdc b/cadence/transactions/updateAccount.cdc index 641b30c..27bb549 100644 --- a/cadence/transactions/updateAccount.cdc +++ b/cadence/transactions/updateAccount.cdc @@ -1,4 +1,4 @@ -import FCL from 0xSERVICE +import "FCL" transaction(address: Address, label: String, scopes: [String]) { prepare() { diff --git a/components/AccountBalances.tsx b/components/AccountBalances.tsx index 2168c35..84378ad 100644 --- a/components/AccountBalances.tsx +++ b/components/AccountBalances.tsx @@ -1,10 +1,9 @@ /** @jsxImportSource theme-ui */ import * as fcl from "@onflow/fcl" import useAccount from "hooks/useAccount" -import useFUSDBalance from "hooks/useFUSDBalance" import {fundAccount} from "src/accounts" import {formattedBalance} from "src/balance" -import {FLOW_TYPE, FUSD_TYPE, TokenTypes} from "src/constants" +import {FLOW_TYPE, TokenTypes} from "src/constants" import useConfig from "hooks/useConfig" import {Label, Themed} from "theme-ui" import {SXStyles} from "types" @@ -42,7 +41,6 @@ export default function AccountBalances({ address: string flowAccountAddress: string }) { - const {data: fusdBalance, refresh: refreshFUSD} = useFUSDBalance(address) const {data: account, refresh: refreshAccount} = useAccount(address) const config = useConfig() @@ -52,7 +50,6 @@ export default function AccountBalances({ const fund = async (token: TokenTypes) => { await fundAccount(config, address, token) refreshAccount() - refreshFUSD() } return ( @@ -76,23 +73,6 @@ export default function AccountBalances({ )} -
- -
- {fusdBalance && formattedBalance(fusdBalance.toString())} -
- {!isServiceAccount && ( - - )} -
) } diff --git a/contexts/ConfigContext.tsx b/contexts/ConfigContext.tsx index 8ea7e9d..7302d29 100644 --- a/contexts/ConfigContext.tsx +++ b/contexts/ConfigContext.tsx @@ -5,10 +5,6 @@ import {getBaseUrl} from "src/utils" interface RuntimeConfig { flowAvatarUrl: string - contractFungibleToken: string - contractFlowToken: string - contractFUSD: string - contractFCLCrypto: string flowAccountAddress: string flowAccountPrivateKey: string flowAccountPublicKey: string @@ -20,10 +16,6 @@ interface RuntimeConfig { const defaultConfig = { flowAvatarUrl: process.env.flowAvatarUrl || "", - contractFungibleToken: process.env.contractFungibleToken || "", - contractFlowToken: process.env.contractFlowToken || "", - contractFUSD: process.env.contractFUSD || "", - contractFCLCrypto: process.env.contractFCLCrypto || "", flowAccountAddress: process.env.flowAccountAddress || "", flowAccountPrivateKey: process.env.flowAccountPrivateKey || "", flowAccountPublicKey: process.env.flowAccountPublicKey || "", @@ -83,22 +75,9 @@ export function ConfigContextProvider({children}: {children: React.ReactNode}) { async function fetchConfig() { const config = await getConfig() - const { - flowAccessNode, - flowAccountAddress, - contractFungibleToken, - contractFlowToken, - contractFUSD, - } = config - - fclConfig( - flowAccessNode, - flowAccountAddress, - contractFungibleToken, - contractFlowToken, - contractFUSD - ) + const {flowAccessNode} = config + fclConfig(flowAccessNode) setConfig(config) } diff --git a/flow.json b/flow.json index e573967..4b833a4 100755 --- a/flow.json +++ b/flow.json @@ -7,26 +7,49 @@ }, "contracts": { "FCL": { - "source": "./cadence/contracts/FCL.cdc" + "source": "./cadence/contracts/FCL.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7" + } + }, + "FCLCrypto": { + "source": "./cadence/contracts/FCLCrypto.cdc", + "aliases": {} }, - "FUSD": { - "source": "./cadence/contracts/FUSD.cdc", + "FlowToken": { + "source": "./cadence/contracts/utility/FlowToken.cdc", "aliases": { - "testnet": "0xe223d8a629e49c68" + "emulator": "0x0ae53cb6e3f42a79" } }, "FungibleToken": { - "source": "./cadence/contracts/FungibleToken.cdc", + "source": "./cadence/contracts/utility/FungibleToken.cdc", "aliases": { "emulator": "0xee82856bf20e2aa6" } }, - "FCLCrypto": { - "source": "./cadence/contracts/FCLCrypto.cdc", + "FungibleTokenMetadataViews": { + "source": "./cadence/contracts/utility/FungibleTokenMetadataViews.cdc", "aliases": { - "emulator": "0xf8d6e0586b0a20c7", - "testnet": "0x74daa6f9c7ef24b1", - "mainnet": "0xb4b82a1c9d21d284" + "emulator": "0xee82856bf20e2aa6" + } + }, + "MetadataViews": { + "source": "./cadence/contracts/utility/MetadataViews.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7" + } + }, + "NonFungibleToken": { + "source": "./cadence/contracts/utility/NonFungibleToken.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7" + } + }, + "ViewResolver": { + "source": "./cadence/contracts/utility/ViewResolver.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7" } } }, @@ -40,10 +63,5 @@ "address": "f8d6e0586b0a20c7", "key": "f8e188e8af0b8b414be59c4a1a15cc666c898fb34d94156e9b51e18bfde754a5" } - }, - "deployments": { - "emulator": { - "emulator-account": ["FUSD"] - } } } diff --git a/go/wallet/.env.development b/go/wallet/.env.development index c8f8ad1..ded8d6c 100644 --- a/go/wallet/.env.development +++ b/go/wallet/.env.development @@ -3,10 +3,6 @@ # We recommend to use the service account defined in the flow.json file your emulator is using. FLOW_INIT_ACCOUNTS=0 -CONTRACT_FUNGIBLE_TOKEN=0xee82856bf20e2aa6 -CONTRACT_FLOW_TOKEN=0x0ae53cb6e3f42a79 -CONTRACT_FUSD=0xf8d6e0586b0a20c7 -CONTRACT_FCL_CRYPTO=0xf8d6e0586b0a20c7 FLOW_AVATAR_URL=https://avatars.onflow.org/avatar/ # EMULATOR REST API ENDPOINT diff --git a/go/wallet/bundle.zip b/go/wallet/bundle.zip index c4a0168..1f70285 100644 Binary files a/go/wallet/bundle.zip and b/go/wallet/bundle.zip differ diff --git a/hooks/useFUSDBalance.ts b/hooks/useFUSDBalance.ts deleted file mode 100644 index 9fa1b67..0000000 --- a/hooks/useFUSDBalance.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {useCallback, useEffect, useState} from "react" -import {getAccountFUSDBalance} from "src/accounts" - -export function compFUSDBalanceKey(address: string) { - return `${address}/fusd-balance` -} - -export function expandFUSDBalanceKey(key: string) { - return { - address: key.split("/")[0], - } -} - -export default function useFUSDBalance(address: string) { - const [balance, setBalance] = useState(null) - const [error, setError] = useState(null) - const [isLoading, setIsLoading] = useState(true) - - const fetchFUSDBalance = useCallback(() => { - getAccountFUSDBalance(address) - .then(balance => { - setBalance(balance) - }) - .catch(error => { - setError(error) - }) - .finally(() => setIsLoading(false)) - }, [address]) - - useEffect(() => { - fetchFUSDBalance() - }, [fetchFUSDBalance]) - - return { - data: balance, - error: error, - isLoading: isLoading, - refresh: fetchFUSDBalance, - } -} diff --git a/next.config.js b/next.config.js index 6f4ce1c..bf39324 100644 --- a/next.config.js +++ b/next.config.js @@ -45,9 +45,5 @@ module.exports = { flowAccountPublicKey: process.env.FLOW_ACCOUNT_PUBLIC_KEY, flowAccessNode: process.env.FLOW_ACCESS_NODE, flowAvatarUrl: process.env.FLOW_AVATAR_URL, - contractFungibleToken: process.env.CONTRACT_FUNGIBLE_TOKEN, - contractFlowToken: process.env.CONTRACT_FLOW_TOKEN, - contractFUSD: process.env.CONTRACT_FUSD, - contractFCLCrypto: process.env.CONTRACT_FCL_CRYPTO, }, } diff --git a/package-lock.json b/package-lock.json index e448684..381f552 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,9 +14,8 @@ "@headlessui/react": "^1.3.0", "@mdx-js/react": "^1.6.22", "@monaco-editor/react": "^4.2.1", - "@onflow/fcl": "^1.5.0-alpha.4", - "@onflow/types": "^0.0.4", - "@onflow/util-encode-key": "^0.0.2", + "@onflow/fcl": "^1.10.0-alpha.4", + "@onflow/types": "^1.3.0-alpha.2", "@theme-ui/color": "^0.14.5", "@theme-ui/css": "^0.14.5", "@theme-ui/match-media": "^0.14.5", @@ -622,16 +621,16 @@ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, "node_modules/@es-joy/jsdoccomment": { - "version": "0.37.1", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.37.1.tgz", - "integrity": "sha512-5vxWJ1gEkEF0yRd0O+uK6dHJf7adrxwQSX8PuRiPfFSAbNLnY0ZJfXaZucoz14Jj2N11xn2DnlEPwWRpYpvRjg==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", + "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", "dependencies": { - "comment-parser": "1.3.1", + "comment-parser": "1.4.1", "esquery": "^1.5.0", "jsdoc-type-pratt-parser": "~4.0.0" }, "engines": { - "node": "^14 || ^16 || ^17 || ^18 || ^19 || ^20" + "node": ">=16" } }, "node_modules/@eslint-community/eslint-utils": { @@ -649,9 +648,9 @@ } }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -660,9 +659,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -720,9 +719,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -769,6 +768,17 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, + "node_modules/@improbable-eng/grpc-web": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", + "integrity": "sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==", + "dependencies": { + "browser-headers": "^0.4.1" + }, + "peerDependencies": { + "google-protobuf": "^3.14.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1181,20 +1191,22 @@ } }, "node_modules/@onflow/config": { - "version": "1.1.1-alpha.0", - "resolved": "https://registry.npmjs.org/@onflow/config/-/config-1.1.1-alpha.0.tgz", - "integrity": "sha512-XuUSXcT2J4BwcJ0c6wpGXTNJqIA/A3VNVpdZVn95nhGy4Sr7qWGnwnNFhTIu++lyvjMQecCS08N2lLgTEeFpbg==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/config/-/config-1.2.2-alpha.2.tgz", + "integrity": "sha512-4p8bWdvqvTq+hgRsEhRT0EgEY6jzKQiwW6LwOzQQXGljFASm6oZjKGSxYtrPy0fl9cDf9YNd28e5QlXbaLNyIw==", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/util-actor": "^1.2.0", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", "eslint": "^8.34.0", - "eslint-plugin-jsdoc": "^40.0.0" + "eslint-plugin-jsdoc": "^46.9.0" } }, "node_modules/@onflow/config/node_modules/@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -1214,22 +1226,27 @@ } }, "node_modules/@onflow/config/node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@onflow/config/node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + }, "node_modules/@onflow/config/node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "bin": { "acorn": "bin/acorn" }, @@ -1288,26 +1305,27 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/@onflow/config/node_modules/eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -1341,9 +1359,9 @@ } }, "node_modules/@onflow/config/node_modules/eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -1356,9 +1374,9 @@ } }, "node_modules/@onflow/config/node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -1409,9 +1427,9 @@ } }, "node_modules/@onflow/config/node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dependencies": { "type-fest": "^0.20.2" }, @@ -1514,55 +1532,49 @@ } }, "node_modules/@onflow/fcl": { - "version": "1.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-1.5.0-alpha.4.tgz", - "integrity": "sha512-P5PxJ1jIGoZ7ReGKBhftaDEnGD61nll8J3Yg0Eo02GdL4497+A7ULlMcz8slZk15s3+KFZJiQlRmgd5jZXWsjg==", + "version": "1.10.0-alpha.4", + "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-1.10.0-alpha.4.tgz", + "integrity": "sha512-CvyJvxCwTRIwmbv6ftKJ6a/FWRC/F1RNd6RGSoNXD7C3b7CCwLTUuItydmxpNaX+kKFL8MmRo4qsWBjSgqGy0w==", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1-alpha.0", + "@onflow/config": "1.2.2-alpha.2", + "@onflow/fcl-core": "1.8.2-alpha.1", "@onflow/interaction": "0.0.11", - "@onflow/rlp": "^1.1.0", - "@onflow/sdk": "^1.2.1-alpha.0", - "@onflow/types": "^1.1.0", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1-alpha.0", - "@onflow/util-template": "^1.1.0", - "@onflow/util-uid": "^1.1.0", - "cross-fetch": "^3.1.6" - }, - "peerDependencies": { - "@react-native-async-storage/async-storage": "^1.13.0", - "expo-linking": "^4.0.0", - "expo-web-browser": "^12.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-native": "^0.0.0-0 || 0.60 - 0.72 || 1000.0.0" - }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - }, - "expo-linking": { - "optional": true - }, - "expo-web-browser": { - "optional": true - }, - "react": { - "optional": true - }, - "react-native": { - "optional": true - } + "@onflow/rlp": "1.2.2-alpha.2", + "@onflow/sdk": "1.4.0-alpha.4", + "@onflow/types": "1.3.0-alpha.2", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-semver": "1.0.2-alpha.0", + "@onflow/util-template": "1.2.2-alpha.2", + "@onflow/util-uid": "1.2.2-alpha.2", + "cross-fetch": "^3.1.6", + "events": "^3.3.0", + "sha3": "^2.1.4" } }, - "node_modules/@onflow/fcl/node_modules/@onflow/types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/types/-/types-1.1.0.tgz", - "integrity": "sha512-UUd2ZAFqdd8BHW//uTg+YRlh3EIH9Na+UYJ9qXpt6y87qjW0Lf4Zkhn6H5IqvhIJsjK17QYnXLFpoXItD/+ToQ==", + "node_modules/@onflow/fcl-core": { + "version": "1.8.2-alpha.1", + "resolved": "https://registry.npmjs.org/@onflow/fcl-core/-/fcl-core-1.8.2-alpha.1.tgz", + "integrity": "sha512-hBU0R5AvVgsSFGEPpkyQem+lGxeBUKwtyHO2io3nIWze6gygTlWE7BngiDCL0p+fPCWpkpiVdrrPABG31T9VrQ==", "dependencies": { - "@babel/runtime": "^7.18.6" + "@babel/runtime": "^7.18.6", + "@improbable-eng/grpc-web": "^0.15.0", + "@onflow/config": "1.2.2-alpha.2", + "@onflow/interaction": "0.0.11", + "@onflow/rlp": "1.2.2-alpha.2", + "@onflow/sdk": "1.4.0-alpha.4", + "@onflow/types": "1.3.0-alpha.2", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-semver": "1.0.2-alpha.0", + "@onflow/util-template": "1.2.2-alpha.2", + "@onflow/util-uid": "1.2.2-alpha.2", + "cross-fetch": "^3.1.6" } }, "node_modules/@onflow/interaction": { @@ -1571,116 +1583,143 @@ "integrity": "sha512-Xuq1Mmx6Wyba/F/L+QLQs0yJeQDsIDwy5SKk5vrCuVgIj0yD8k506g5L8ODrbM1LWll8i0tQsoOi0F85vNl5sA==" }, "node_modules/@onflow/rlp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/rlp/-/rlp-1.1.0.tgz", - "integrity": "sha512-JJj4dZpKaWmCOXnado+D3RU5xYAXui9kHOmCVfdLReYHIsYBgxwHCDO/hDiQjrbmfLpiybbJKTaIldu+xkCU3Q==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/rlp/-/rlp-1.2.2-alpha.2.tgz", + "integrity": "sha512-W18UFAE1TXHlyypC1+G4WpUKXjd1IQbx6VaLXFDB1fbYkxuWOkrsKVaLPfKd6Y7/Cij6cNJI4F9J5su4bnUysw==", "dependencies": { "@babel/runtime": "^7.18.6", "buffer": "^6.0.3" } }, "node_modules/@onflow/sdk": { - "version": "1.2.1-alpha.1", - "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-1.2.1-alpha.1.tgz", - "integrity": "sha512-4wvlhiIbQ1NuhVsK1SAWtz4MeaXQr3S5qXq51+lEZ/xpKA1Eggnn6SDUhbLeW6eBCxDZef4CbEBx3sQxz2RHSw==", + "version": "1.4.0-alpha.4", + "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-1.4.0-alpha.4.tgz", + "integrity": "sha512-5GskQh8d2vGci/gadoDIqQgLnJpXGxySrFueU2SL6trMsZyoIe3D2dP2rbHhYyB392bcornV0fao/J1MH/cn2w==", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1-alpha.0", - "@onflow/rlp": "^1.1.0", - "@onflow/transport-http": "^1.7.0-alpha.0", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1-alpha.0", - "@onflow/util-template": "^1.1.0", + "@onflow/config": "1.2.2-alpha.2", + "@onflow/rlp": "1.2.2-alpha.2", + "@onflow/transport-http": "1.10.0-alpha.3", + "@onflow/typedefs": "1.3.0-alpha.2", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-template": "1.2.2-alpha.2", "deepmerge": "^4.2.2", - "sha3": "^2.1.4" + "events": "^3.3.0", + "sha3": "^2.1.4", + "uuid": "^9.0.1" + } + }, + "node_modules/@onflow/sdk/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/@onflow/transport-http": { - "version": "1.7.0-alpha.0", - "resolved": "https://registry.npmjs.org/@onflow/transport-http/-/transport-http-1.7.0-alpha.0.tgz", - "integrity": "sha512-g3m78rOeRnkkk18lumjdQ4vuKbfWXwfn2NNNoEI73V6L7nKlKOVePJrqSrBwI/lWG2z+j58FIpu0cHHqCsUqXg==", + "version": "1.10.0-alpha.3", + "resolved": "https://registry.npmjs.org/@onflow/transport-http/-/transport-http-1.10.0-alpha.3.tgz", + "integrity": "sha512-aruhfGIDdTomrzekDFd5oAM7Q5fJO0htTwuyz7mOc57gOxN00/CjJF05dianlBBdPP1NGUcuqynsZ6PX3cSDjQ==", "dependencies": { "@babel/runtime": "^7.18.6", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1-alpha.0", - "@onflow/util-template": "^1.1.0", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-template": "1.2.2-alpha.2", "abort-controller": "^3.0.0", - "cross-fetch": "^3.1.6" + "cross-fetch": "^3.1.6", + "events": "^3.3.0", + "isomorphic-ws": "^5.0.0", + "ws": "^8.14.2" + } + }, + "node_modules/@onflow/typedefs": { + "version": "1.3.0-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/typedefs/-/typedefs-1.3.0-alpha.2.tgz", + "integrity": "sha512-boy22ChDls+76inLpr/JPHsvkEsS02374oPdHaFy06peUqfGGrMly7lxL2e/54oqUcZA9F0wCS53OeVrXnCwjw==", + "dependencies": { + "@babel/runtime": "^7.18.6" } }, "node_modules/@onflow/types": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@onflow/types/-/types-0.0.4.tgz", - "integrity": "sha512-47r0qTM45mR7FSvyEE0njGljkpgy3MCf/2W82pfZ/PTFGWr1nsGV/4j2bUfK9Sry4Ymz2W20iRZVP3xpqOhqGw==" + "version": "1.3.0-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/types/-/types-1.3.0-alpha.2.tgz", + "integrity": "sha512-D1fp6/+UmNkTyKuyBIFmf182cRkq3Yjo9bgUEbipjX254KwSPVYcprHLR71JGdbcN5RuzvW07XHj2Q2VUX9PGw==", + "dependencies": { + "@babel/runtime": "^7.18.6", + "@onflow/util-logger": "1.3.2-alpha.2" + } }, "node_modules/@onflow/util-actor": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@onflow/util-actor/-/util-actor-1.2.0.tgz", - "integrity": "sha512-voyHXE3qYNC+P75vzv55pGDDwpxxWKWH0aToR/3g9Bq8nKGcGoszxaMJkVy+fKX1akfdT0yKr/GxXRkjCS9SBg==", + "version": "1.3.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-actor/-/util-actor-1.3.2-alpha.2.tgz", + "integrity": "sha512-oVuYidjtujVzaSZ5PgSGM7G4OJ5MYxpttnFxuRnKLizulGsOi+qqfuFW40HxyzhZHWOp+2lnkt9Fqk6s+cuDDA==", "dependencies": { "@babel/runtime": "^7.18.6", "queue-microtask": "1.2.3" } }, "node_modules/@onflow/util-address": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-address/-/util-address-1.1.0.tgz", - "integrity": "sha512-HhJOIfNaYAoeYuTNUe85jt4fqnJhFmSbYqyufiJBrplwd3eKmNsan0NYvVYO4U1ecu3KyuY4D9R/NtjGpHjMlA==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-address/-/util-address-1.2.2-alpha.2.tgz", + "integrity": "sha512-Fup1GkMwurljMHTNUcP6UqP/ln+XwnKE8cWjiPiaCnK4NJMrU4jaobrc6aEbZoYIrj8suklfrjvHUuCZ+7DGfQ==", "dependencies": { "@babel/runtime": "^7.18.6" } }, - "node_modules/@onflow/util-encode-key": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@onflow/util-encode-key/-/util-encode-key-0.0.2.tgz", - "integrity": "sha512-gY9H4f1USijXbgk6IoNibAibF8VB6spZgq2fdkxA9PKgKay6UjolnsKTvIkA0k4/CIiODQIh5ziL069mrRjOJw==", + "node_modules/@onflow/util-invariant": { + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-invariant/-/util-invariant-1.2.2-alpha.2.tgz", + "integrity": "sha512-m7PqZ6RQ4QecpFiYSKMoghT2iT9ceza/qv8Usw2csntcUWOkA+x2hxKh/pUoa8LGK5054gemfNtFac2J9cPOKw==", "dependencies": { - "@onflow/rlp": "0.0.3", - "@onflow/util-invariant": "0.0.0" + "@babel/runtime": "^7.18.6" } }, - "node_modules/@onflow/util-encode-key/node_modules/@onflow/rlp": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@onflow/rlp/-/rlp-0.0.3.tgz", - "integrity": "sha512-oAf0VEiMjX8eC6Vd66j1BdGYTHOM6UBaS/sLSScnc7bKX5gICqe2gtEsCeJVE9rUzRk3GD3JqXRnPAW6YFWd/Q==" - }, - "node_modules/@onflow/util-encode-key/node_modules/@onflow/util-invariant": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/@onflow/util-invariant/-/util-invariant-0.0.0.tgz", - "integrity": "sha512-ZCt+NqLdeHt9tZhb0DGxo6iSIS9oNUpLkd0PEMzUYUHr4UwrUO7VruV1AUW3PaF9V78DZ13fNZUiQEzdF76O/w==" - }, - "node_modules/@onflow/util-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-invariant/-/util-invariant-1.1.0.tgz", - "integrity": "sha512-5uxweKl5tqeqB1QLzs3dWWLtpNo7H4PgcmgnRIcC2oItAkELcnVCybDdlfYjKB4n/dlg3rIym8cJQE2tBeOpZQ==", + "node_modules/@onflow/util-logger": { + "version": "1.3.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-logger/-/util-logger-1.3.2-alpha.2.tgz", + "integrity": "sha512-6mLXIp/7n3bmaxVJcGZVQ0rrJipM6pKEkmH752VTzn8ObXM3HtV91ee86GlY0pH1r64ntnsa+KvOhpmo1kMT8A==", "dependencies": { "@babel/runtime": "^7.18.6" + }, + "peerDependencies": { + "@onflow/util-config": ">1.1.1" + }, + "peerDependenciesMeta": { + "@onflow/util-config": { + "optional": true + } } }, - "node_modules/@onflow/util-logger": { - "version": "1.2.1-alpha.0", - "resolved": "https://registry.npmjs.org/@onflow/util-logger/-/util-logger-1.2.1-alpha.0.tgz", - "integrity": "sha512-JJ0p3O/JoKQzWdyFo4ZNMZ/gGwHrV3k0GoxF/pp6A8ghlNJgNTMgrF7mz3J+nsznaDqXJKGYi7YdcEIH5Rmesg==", + "node_modules/@onflow/util-semver": { + "version": "1.0.2-alpha.0", + "resolved": "https://registry.npmjs.org/@onflow/util-semver/-/util-semver-1.0.2-alpha.0.tgz", + "integrity": "sha512-q+Y8FnQSPiK9911rNXWkNWNQhtLvBQgnROTIxxmi21PUaf5m5QAj/kuZ8SI4LOh0GcdP+QHvv9LzoBkQiSk2Tg==", "dependencies": { - "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1-alpha.0" + "@babel/runtime": "^7.18.6" } }, "node_modules/@onflow/util-template": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-template/-/util-template-1.1.0.tgz", - "integrity": "sha512-gGqJJH5OTPPRmHk6YxMw4t5Ecy7iHnj00ZlCE7lnlOnpGUNdHrNNfoeE//hO8TBGNNVpOkEQERWiLDph+/oIxg==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-template/-/util-template-1.2.2-alpha.2.tgz", + "integrity": "sha512-p+jS1ORr1urEeU7AfoqpP3uOaEgulKrjCOAf4FciyAXo1Dod/+JjPwewW/gv3Yk5fE6TlP9sx74Dg/zLsEAEAQ==", "dependencies": { - "@babel/runtime": "^7.18.6" + "@babel/runtime": "^7.18.6", + "@onflow/util-logger": "1.3.2-alpha.2" } }, "node_modules/@onflow/util-uid": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-uid/-/util-uid-1.1.0.tgz", - "integrity": "sha512-HmWfKCOXoz1/TIu7fRx6iR7Nfhq6q5Tmn4YWc868SIfFeWv/inpvVJyrKX0nORf87csSnRSqdDzrJGBowgcXVA==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-uid/-/util-uid-1.2.2-alpha.2.tgz", + "integrity": "sha512-GUYPQL47FprUWlGHIXQsfoifcAvX9OA1S+wszVHikaH+F4zheWoCJd7EIfojEPEv66CS2aBwcKIbT/z73os9UQ==", "dependencies": { "@babel/runtime": "^7.18.6" } @@ -2257,6 +2296,11 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -2377,6 +2421,14 @@ } ] }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2687,6 +2739,11 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, + "node_modules/browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, "node_modules/browserslist": { "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", @@ -2747,6 +2804,17 @@ "node": "*" } }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cachedir": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", @@ -2946,9 +3014,9 @@ } }, "node_modules/comment-parser": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", - "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "engines": { "node": ">= 12.0.0" } @@ -3833,23 +3901,25 @@ "dev": true }, "node_modules/eslint-plugin-jsdoc": { - "version": "40.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-40.3.0.tgz", - "integrity": "sha512-EhCqpzRkxoT2DUB4AnrU0ggBYvTh3bWrLZzQTupq6vSVE6XzNwJVKsOHa41GCoevnsWMBNmoDVjXWGqckjuG1g==", + "version": "46.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.10.1.tgz", + "integrity": "sha512-x8wxIpv00Y50NyweDUpa+58ffgSAI5sqe+zcZh33xphD0AVh+1kqr1ombaTRb7Fhpove1zfUuujlX9DWWBP5ag==", "dependencies": { - "@es-joy/jsdoccomment": "~0.37.0", - "comment-parser": "1.3.1", + "@es-joy/jsdoccomment": "~0.41.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "esquery": "^1.5.0", - "semver": "^7.3.8", - "spdx-expression-parse": "^3.0.1" + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^4.0.0" }, "engines": { - "node": "^14 || ^16 || ^17 || ^18 || ^19" + "node": ">=16" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-plugin-jsdoc/node_modules/semver": { @@ -4250,6 +4320,14 @@ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==", "dev": true }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", @@ -4762,6 +4840,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==", + "peer": true + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -5024,6 +5108,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-callable": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", @@ -5266,6 +5364,14 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -5894,9 +6000,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -6883,18 +6989,18 @@ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" }, "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==" + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==" }, "node_modules/sprintf-js": { "version": "1.0.3", @@ -7740,6 +7846,26 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "node_modules/ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -8263,11 +8389,11 @@ "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" }, "@es-joy/jsdoccomment": { - "version": "0.37.1", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.37.1.tgz", - "integrity": "sha512-5vxWJ1gEkEF0yRd0O+uK6dHJf7adrxwQSX8PuRiPfFSAbNLnY0ZJfXaZucoz14Jj2N11xn2DnlEPwWRpYpvRjg==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", + "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", "requires": { - "comment-parser": "1.3.1", + "comment-parser": "1.4.1", "esquery": "^1.5.0", "jsdoc-type-pratt-parser": "~4.0.0" } @@ -8281,16 +8407,16 @@ }, "dependencies": { "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==" + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" } } }, "@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==" + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==" }, "@eslint/eslintrc": { "version": "0.4.3", @@ -8329,9 +8455,9 @@ } }, "@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==" + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==" }, "@headlessui/react": { "version": "1.6.1", @@ -8359,6 +8485,14 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, + "@improbable-eng/grpc-web": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.15.0.tgz", + "integrity": "sha512-ERft9/0/8CmYalqOVnJnpdDry28q+j+nAlFFARdjyxXDJ+Mhgv9+F600QC8BR9ygOfrXRlAk6CvST2j+JCpQPg==", + "requires": { + "browser-headers": "^0.4.1" + } + }, "@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -8591,20 +8725,22 @@ } }, "@onflow/config": { - "version": "1.1.1-alpha.0", - "resolved": "https://registry.npmjs.org/@onflow/config/-/config-1.1.1-alpha.0.tgz", - "integrity": "sha512-XuUSXcT2J4BwcJ0c6wpGXTNJqIA/A3VNVpdZVn95nhGy4Sr7qWGnwnNFhTIu++lyvjMQecCS08N2lLgTEeFpbg==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/config/-/config-1.2.2-alpha.2.tgz", + "integrity": "sha512-4p8bWdvqvTq+hgRsEhRT0EgEY6jzKQiwW6LwOzQQXGljFASm6oZjKGSxYtrPy0fl9cDf9YNd28e5QlXbaLNyIw==", "requires": { "@babel/runtime": "^7.18.6", - "@onflow/util-actor": "^1.2.0", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", "eslint": "^8.34.0", - "eslint-plugin-jsdoc": "^40.0.0" + "eslint-plugin-jsdoc": "^46.9.0" }, "dependencies": { "@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -8618,19 +8754,24 @@ } }, "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" } }, + "@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==" + }, "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==" }, "ansi-styles": { "version": "4.3.0", @@ -8668,26 +8809,27 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -8712,18 +8854,18 @@ } }, "eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "requires": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==" + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" }, "espree": { "version": "9.6.1", @@ -8753,9 +8895,9 @@ } }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "requires": { "type-fest": "^0.20.2" } @@ -8818,33 +8960,49 @@ } }, "@onflow/fcl": { - "version": "1.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-1.5.0-alpha.4.tgz", - "integrity": "sha512-P5PxJ1jIGoZ7ReGKBhftaDEnGD61nll8J3Yg0Eo02GdL4497+A7ULlMcz8slZk15s3+KFZJiQlRmgd5jZXWsjg==", + "version": "1.10.0-alpha.4", + "resolved": "https://registry.npmjs.org/@onflow/fcl/-/fcl-1.10.0-alpha.4.tgz", + "integrity": "sha512-CvyJvxCwTRIwmbv6ftKJ6a/FWRC/F1RNd6RGSoNXD7C3b7CCwLTUuItydmxpNaX+kKFL8MmRo4qsWBjSgqGy0w==", + "requires": { + "@babel/runtime": "^7.18.6", + "@onflow/config": "1.2.2-alpha.2", + "@onflow/fcl-core": "1.8.2-alpha.1", + "@onflow/interaction": "0.0.11", + "@onflow/rlp": "1.2.2-alpha.2", + "@onflow/sdk": "1.4.0-alpha.4", + "@onflow/types": "1.3.0-alpha.2", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-semver": "1.0.2-alpha.0", + "@onflow/util-template": "1.2.2-alpha.2", + "@onflow/util-uid": "1.2.2-alpha.2", + "cross-fetch": "^3.1.6", + "events": "^3.3.0", + "sha3": "^2.1.4" + } + }, + "@onflow/fcl-core": { + "version": "1.8.2-alpha.1", + "resolved": "https://registry.npmjs.org/@onflow/fcl-core/-/fcl-core-1.8.2-alpha.1.tgz", + "integrity": "sha512-hBU0R5AvVgsSFGEPpkyQem+lGxeBUKwtyHO2io3nIWze6gygTlWE7BngiDCL0p+fPCWpkpiVdrrPABG31T9VrQ==", "requires": { "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1-alpha.0", + "@improbable-eng/grpc-web": "^0.15.0", + "@onflow/config": "1.2.2-alpha.2", "@onflow/interaction": "0.0.11", - "@onflow/rlp": "^1.1.0", - "@onflow/sdk": "^1.2.1-alpha.0", - "@onflow/types": "^1.1.0", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1-alpha.0", - "@onflow/util-template": "^1.1.0", - "@onflow/util-uid": "^1.1.0", + "@onflow/rlp": "1.2.2-alpha.2", + "@onflow/sdk": "1.4.0-alpha.4", + "@onflow/types": "1.3.0-alpha.2", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-semver": "1.0.2-alpha.0", + "@onflow/util-template": "1.2.2-alpha.2", + "@onflow/util-uid": "1.2.2-alpha.2", "cross-fetch": "^3.1.6" - }, - "dependencies": { - "@onflow/types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/types/-/types-1.1.0.tgz", - "integrity": "sha512-UUd2ZAFqdd8BHW//uTg+YRlh3EIH9Na+UYJ9qXpt6y87qjW0Lf4Zkhn6H5IqvhIJsjK17QYnXLFpoXItD/+ToQ==", - "requires": { - "@babel/runtime": "^7.18.6" - } - } } }, "@onflow/interaction": { @@ -8853,118 +9011,130 @@ "integrity": "sha512-Xuq1Mmx6Wyba/F/L+QLQs0yJeQDsIDwy5SKk5vrCuVgIj0yD8k506g5L8ODrbM1LWll8i0tQsoOi0F85vNl5sA==" }, "@onflow/rlp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/rlp/-/rlp-1.1.0.tgz", - "integrity": "sha512-JJj4dZpKaWmCOXnado+D3RU5xYAXui9kHOmCVfdLReYHIsYBgxwHCDO/hDiQjrbmfLpiybbJKTaIldu+xkCU3Q==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/rlp/-/rlp-1.2.2-alpha.2.tgz", + "integrity": "sha512-W18UFAE1TXHlyypC1+G4WpUKXjd1IQbx6VaLXFDB1fbYkxuWOkrsKVaLPfKd6Y7/Cij6cNJI4F9J5su4bnUysw==", "requires": { "@babel/runtime": "^7.18.6", "buffer": "^6.0.3" } }, "@onflow/sdk": { - "version": "1.2.1-alpha.1", - "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-1.2.1-alpha.1.tgz", - "integrity": "sha512-4wvlhiIbQ1NuhVsK1SAWtz4MeaXQr3S5qXq51+lEZ/xpKA1Eggnn6SDUhbLeW6eBCxDZef4CbEBx3sQxz2RHSw==", + "version": "1.4.0-alpha.4", + "resolved": "https://registry.npmjs.org/@onflow/sdk/-/sdk-1.4.0-alpha.4.tgz", + "integrity": "sha512-5GskQh8d2vGci/gadoDIqQgLnJpXGxySrFueU2SL6trMsZyoIe3D2dP2rbHhYyB392bcornV0fao/J1MH/cn2w==", "requires": { "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1-alpha.0", - "@onflow/rlp": "^1.1.0", - "@onflow/transport-http": "^1.7.0-alpha.0", - "@onflow/util-actor": "^1.2.0", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1-alpha.0", - "@onflow/util-template": "^1.1.0", + "@onflow/config": "1.2.2-alpha.2", + "@onflow/rlp": "1.2.2-alpha.2", + "@onflow/transport-http": "1.10.0-alpha.3", + "@onflow/typedefs": "1.3.0-alpha.2", + "@onflow/util-actor": "1.3.2-alpha.2", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-template": "1.2.2-alpha.2", "deepmerge": "^4.2.2", - "sha3": "^2.1.4" + "events": "^3.3.0", + "sha3": "^2.1.4", + "uuid": "^9.0.1" + }, + "dependencies": { + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + } } }, "@onflow/transport-http": { - "version": "1.7.0-alpha.0", - "resolved": "https://registry.npmjs.org/@onflow/transport-http/-/transport-http-1.7.0-alpha.0.tgz", - "integrity": "sha512-g3m78rOeRnkkk18lumjdQ4vuKbfWXwfn2NNNoEI73V6L7nKlKOVePJrqSrBwI/lWG2z+j58FIpu0cHHqCsUqXg==", + "version": "1.10.0-alpha.3", + "resolved": "https://registry.npmjs.org/@onflow/transport-http/-/transport-http-1.10.0-alpha.3.tgz", + "integrity": "sha512-aruhfGIDdTomrzekDFd5oAM7Q5fJO0htTwuyz7mOc57gOxN00/CjJF05dianlBBdPP1NGUcuqynsZ6PX3cSDjQ==", "requires": { "@babel/runtime": "^7.18.6", - "@onflow/util-address": "^1.1.0", - "@onflow/util-invariant": "^1.1.0", - "@onflow/util-logger": "^1.2.1-alpha.0", - "@onflow/util-template": "^1.1.0", + "@onflow/util-address": "1.2.2-alpha.2", + "@onflow/util-invariant": "1.2.2-alpha.2", + "@onflow/util-logger": "1.3.2-alpha.2", + "@onflow/util-template": "1.2.2-alpha.2", "abort-controller": "^3.0.0", - "cross-fetch": "^3.1.6" + "cross-fetch": "^3.1.6", + "events": "^3.3.0", + "isomorphic-ws": "^5.0.0", + "ws": "^8.14.2" + } + }, + "@onflow/typedefs": { + "version": "1.3.0-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/typedefs/-/typedefs-1.3.0-alpha.2.tgz", + "integrity": "sha512-boy22ChDls+76inLpr/JPHsvkEsS02374oPdHaFy06peUqfGGrMly7lxL2e/54oqUcZA9F0wCS53OeVrXnCwjw==", + "requires": { + "@babel/runtime": "^7.18.6" } }, "@onflow/types": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@onflow/types/-/types-0.0.4.tgz", - "integrity": "sha512-47r0qTM45mR7FSvyEE0njGljkpgy3MCf/2W82pfZ/PTFGWr1nsGV/4j2bUfK9Sry4Ymz2W20iRZVP3xpqOhqGw==" + "version": "1.3.0-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/types/-/types-1.3.0-alpha.2.tgz", + "integrity": "sha512-D1fp6/+UmNkTyKuyBIFmf182cRkq3Yjo9bgUEbipjX254KwSPVYcprHLR71JGdbcN5RuzvW07XHj2Q2VUX9PGw==", + "requires": { + "@babel/runtime": "^7.18.6", + "@onflow/util-logger": "1.3.2-alpha.2" + } }, "@onflow/util-actor": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@onflow/util-actor/-/util-actor-1.2.0.tgz", - "integrity": "sha512-voyHXE3qYNC+P75vzv55pGDDwpxxWKWH0aToR/3g9Bq8nKGcGoszxaMJkVy+fKX1akfdT0yKr/GxXRkjCS9SBg==", + "version": "1.3.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-actor/-/util-actor-1.3.2-alpha.2.tgz", + "integrity": "sha512-oVuYidjtujVzaSZ5PgSGM7G4OJ5MYxpttnFxuRnKLizulGsOi+qqfuFW40HxyzhZHWOp+2lnkt9Fqk6s+cuDDA==", "requires": { "@babel/runtime": "^7.18.6", "queue-microtask": "1.2.3" } }, "@onflow/util-address": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-address/-/util-address-1.1.0.tgz", - "integrity": "sha512-HhJOIfNaYAoeYuTNUe85jt4fqnJhFmSbYqyufiJBrplwd3eKmNsan0NYvVYO4U1ecu3KyuY4D9R/NtjGpHjMlA==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-address/-/util-address-1.2.2-alpha.2.tgz", + "integrity": "sha512-Fup1GkMwurljMHTNUcP6UqP/ln+XwnKE8cWjiPiaCnK4NJMrU4jaobrc6aEbZoYIrj8suklfrjvHUuCZ+7DGfQ==", "requires": { "@babel/runtime": "^7.18.6" } }, - "@onflow/util-encode-key": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@onflow/util-encode-key/-/util-encode-key-0.0.2.tgz", - "integrity": "sha512-gY9H4f1USijXbgk6IoNibAibF8VB6spZgq2fdkxA9PKgKay6UjolnsKTvIkA0k4/CIiODQIh5ziL069mrRjOJw==", + "@onflow/util-invariant": { + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-invariant/-/util-invariant-1.2.2-alpha.2.tgz", + "integrity": "sha512-m7PqZ6RQ4QecpFiYSKMoghT2iT9ceza/qv8Usw2csntcUWOkA+x2hxKh/pUoa8LGK5054gemfNtFac2J9cPOKw==", "requires": { - "@onflow/rlp": "0.0.3", - "@onflow/util-invariant": "0.0.0" - }, - "dependencies": { - "@onflow/rlp": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@onflow/rlp/-/rlp-0.0.3.tgz", - "integrity": "sha512-oAf0VEiMjX8eC6Vd66j1BdGYTHOM6UBaS/sLSScnc7bKX5gICqe2gtEsCeJVE9rUzRk3GD3JqXRnPAW6YFWd/Q==" - }, - "@onflow/util-invariant": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/@onflow/util-invariant/-/util-invariant-0.0.0.tgz", - "integrity": "sha512-ZCt+NqLdeHt9tZhb0DGxo6iSIS9oNUpLkd0PEMzUYUHr4UwrUO7VruV1AUW3PaF9V78DZ13fNZUiQEzdF76O/w==" - } + "@babel/runtime": "^7.18.6" } }, - "@onflow/util-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-invariant/-/util-invariant-1.1.0.tgz", - "integrity": "sha512-5uxweKl5tqeqB1QLzs3dWWLtpNo7H4PgcmgnRIcC2oItAkELcnVCybDdlfYjKB4n/dlg3rIym8cJQE2tBeOpZQ==", + "@onflow/util-logger": { + "version": "1.3.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-logger/-/util-logger-1.3.2-alpha.2.tgz", + "integrity": "sha512-6mLXIp/7n3bmaxVJcGZVQ0rrJipM6pKEkmH752VTzn8ObXM3HtV91ee86GlY0pH1r64ntnsa+KvOhpmo1kMT8A==", "requires": { "@babel/runtime": "^7.18.6" } }, - "@onflow/util-logger": { - "version": "1.2.1-alpha.0", - "resolved": "https://registry.npmjs.org/@onflow/util-logger/-/util-logger-1.2.1-alpha.0.tgz", - "integrity": "sha512-JJ0p3O/JoKQzWdyFo4ZNMZ/gGwHrV3k0GoxF/pp6A8ghlNJgNTMgrF7mz3J+nsznaDqXJKGYi7YdcEIH5Rmesg==", + "@onflow/util-semver": { + "version": "1.0.2-alpha.0", + "resolved": "https://registry.npmjs.org/@onflow/util-semver/-/util-semver-1.0.2-alpha.0.tgz", + "integrity": "sha512-q+Y8FnQSPiK9911rNXWkNWNQhtLvBQgnROTIxxmi21PUaf5m5QAj/kuZ8SI4LOh0GcdP+QHvv9LzoBkQiSk2Tg==", "requires": { - "@babel/runtime": "^7.18.6", - "@onflow/config": "^1.1.1-alpha.0" + "@babel/runtime": "^7.18.6" } }, "@onflow/util-template": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-template/-/util-template-1.1.0.tgz", - "integrity": "sha512-gGqJJH5OTPPRmHk6YxMw4t5Ecy7iHnj00ZlCE7lnlOnpGUNdHrNNfoeE//hO8TBGNNVpOkEQERWiLDph+/oIxg==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-template/-/util-template-1.2.2-alpha.2.tgz", + "integrity": "sha512-p+jS1ORr1urEeU7AfoqpP3uOaEgulKrjCOAf4FciyAXo1Dod/+JjPwewW/gv3Yk5fE6TlP9sx74Dg/zLsEAEAQ==", "requires": { - "@babel/runtime": "^7.18.6" + "@babel/runtime": "^7.18.6", + "@onflow/util-logger": "1.3.2-alpha.2" } }, "@onflow/util-uid": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@onflow/util-uid/-/util-uid-1.1.0.tgz", - "integrity": "sha512-HmWfKCOXoz1/TIu7fRx6iR7Nfhq6q5Tmn4YWc868SIfFeWv/inpvVJyrKX0nORf87csSnRSqdDzrJGBowgcXVA==", + "version": "1.2.2-alpha.2", + "resolved": "https://registry.npmjs.org/@onflow/util-uid/-/util-uid-1.2.2-alpha.2.tgz", + "integrity": "sha512-GUYPQL47FprUWlGHIXQsfoifcAvX9OA1S+wszVHikaH+F4zheWoCJd7EIfojEPEv66CS2aBwcKIbT/z73os9UQ==", "requires": { "@babel/runtime": "^7.18.6" } @@ -9427,6 +9597,11 @@ "eslint-visitor-keys": "^2.0.0" } }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -9500,6 +9675,11 @@ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true }, + "are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -9743,6 +9923,11 @@ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" }, + "browser-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz", + "integrity": "sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg==" + }, "browserslist": { "version": "4.21.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", @@ -9770,6 +9955,11 @@ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" + }, "cachedir": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", @@ -9917,9 +10107,9 @@ "dev": true }, "comment-parser": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", - "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==" }, "common-tags": { "version": "1.8.2", @@ -10708,17 +10898,19 @@ } }, "eslint-plugin-jsdoc": { - "version": "40.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-40.3.0.tgz", - "integrity": "sha512-EhCqpzRkxoT2DUB4AnrU0ggBYvTh3bWrLZzQTupq6vSVE6XzNwJVKsOHa41GCoevnsWMBNmoDVjXWGqckjuG1g==", + "version": "46.10.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.10.1.tgz", + "integrity": "sha512-x8wxIpv00Y50NyweDUpa+58ffgSAI5sqe+zcZh33xphD0AVh+1kqr1ombaTRb7Fhpove1zfUuujlX9DWWBP5ag==", "requires": { - "@es-joy/jsdoccomment": "~0.37.0", - "comment-parser": "1.3.1", + "@es-joy/jsdoccomment": "~0.41.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "esquery": "^1.5.0", - "semver": "^7.3.8", - "spdx-expression-parse": "^3.0.1" + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^4.0.0" }, "dependencies": { "semver": { @@ -10899,6 +11091,11 @@ "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==", "dev": true }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, "execa": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", @@ -11282,6 +11479,12 @@ "slash": "^3.0.0" } }, + "google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==", + "peer": true + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -11472,6 +11675,14 @@ "has-tostringtag": "^1.0.0" } }, + "is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "requires": { + "builtin-modules": "^3.3.0" + } + }, "is-callable": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", @@ -11627,6 +11838,12 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "requires": {} + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -12095,9 +12312,9 @@ } }, "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "requires": { "whatwg-url": "^5.0.0" } @@ -12799,18 +13016,18 @@ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" }, "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==" + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==" }, "sprintf-js": { "version": "1.0.3", @@ -13443,6 +13660,12 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "ws": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", + "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", + "requires": {} + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 724e05b..118ce0d 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,8 @@ "@headlessui/react": "^1.3.0", "@mdx-js/react": "^1.6.22", "@monaco-editor/react": "^4.2.1", - "@onflow/fcl": "^1.5.0-alpha.4", - "@onflow/types": "^0.0.4", - "@onflow/util-encode-key": "^0.0.2", + "@onflow/fcl": "^1.10.0-alpha.4", + "@onflow/types": "^1.3.0-alpha.2", "@theme-ui/color": "^0.14.5", "@theme-ui/css": "^0.14.5", "@theme-ui/match-media": "^0.14.5", diff --git a/src/accounts.ts b/src/accounts.ts index 3d33149..b76623c 100644 --- a/src/accounts.ts +++ b/src/accounts.ts @@ -4,16 +4,14 @@ import {Optional} from "types" import getAccountsScript from "cadence/scripts/getAccounts.cdc" import getAccountScript from "cadence/scripts/getAccount.cdc" -import getFUSDBalanceScript from "cadence/scripts/getFUSDBalance.cdc" import newAccountTransaction from "cadence/transactions/newAccount.cdc" import updateAccountTransaction from "cadence/transactions/updateAccount.cdc" import fundAccountFLOWTransaction from "cadence/transactions/fundFLOW.cdc" -import fundAccountFUSDTransaction from "cadence/transactions/fundFUSD.cdc" import {authz} from "src/authz" import {FLOW_EVENT_TYPES} from "src/constants" -import {FLOW_TYPE, FUSD_TYPE, TokenType, TokenTypes} from "src/constants" +import {FLOW_TYPE, TokenType, TokenTypes} from "src/constants" export type Account = { type: "ACCOUNT" @@ -49,6 +47,8 @@ export async function getAccount(address: string) { export async function getAccounts(config: {flowAccountAddress: string}) { const {flowAccountAddress} = config + fcl.config().all().then(console.log) + const accounts = await fcl .send([fcl.script(getAccountsScript)]) .then(fcl.decode) @@ -157,7 +157,6 @@ type Tokens = Record export const TOKEN_FUNDING_AMOUNTS: Record = { FLOW: "100.0", - FUSD: "100.0", } export const tokens: Tokens = { @@ -165,10 +164,6 @@ export const tokens: Tokens = { tx: fundAccountFLOWTransaction, amount: TOKEN_FUNDING_AMOUNTS[FLOW_TYPE], }, - FUSD: { - tx: fundAccountFUSDTransaction, - amount: TOKEN_FUNDING_AMOUNTS[FUSD_TYPE], - }, } export async function fundAccount( @@ -182,7 +177,7 @@ export async function fundAccount( ) { const {flowAccountAddress, flowAccountKeyId, flowAccountPrivateKey} = config - if (!["FUSD", "FLOW"].includes(token)) { + if (!["FLOW"].includes(token)) { throw "Incorrect TokenType" } @@ -192,16 +187,9 @@ export async function fundAccount( flowAccountPrivateKey ) - const acctAuthz = await authz( - address, - flowAccountKeyId, - flowAccountPrivateKey - ) - const {tx, amount} = tokens[token] - const authorizations = - token === FUSD_TYPE ? [minterAuthz, acctAuthz] : [minterAuthz] + const authorizations = [minterAuthz] const txId = await fcl .send([ @@ -216,14 +204,3 @@ export async function fundAccount( await fcl.tx(txId).onceSealed() } - -export async function getAccountFUSDBalance(address: string): Promise { - const balance = await fcl - .send([ - fcl.script(getFUSDBalanceScript), - fcl.args([fcl.arg(address, t.Address)]), - ]) - .then(fcl.decode) - - return balance -} diff --git a/src/constants.ts b/src/constants.ts index 38d0d2f..3f6f315 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -7,7 +7,6 @@ export const SERVICE_ACCOUNT_LABEL = "Service Account" export const UNTITLED_APP_NAME = "Untitled Dapp" export const FLOW_TYPE = "FLOW" -export const FUSD_TYPE = "FUSD" -export type TokenTypes = typeof FLOW_TYPE | typeof FUSD_TYPE -export type TokenType = "FLOW" | "FUSD" +export type TokenTypes = typeof FLOW_TYPE +export type TokenType = "FLOW" diff --git a/src/crypto.ts b/src/crypto.ts index 2e07f6b..a31dc9a 100644 --- a/src/crypto.ts +++ b/src/crypto.ts @@ -1,13 +1,23 @@ -import {ECDSA_P256, encodeKey, SHA3_256} from "@onflow/util-encode-key" import {ec as EC} from "elliptic" import {SHA3} from "sha3" -const ec = new EC("p256") +export enum HashAlgorithm { + SHA2_256 = 1, + SHA2_384 = 2, + SHA3_256 = 3, + SHA3_384 = 4, + KMAC128_BLS_BLS12_381 = 5, + KECCAK_256 = 6, +} -export const encodeServiceKey = (flowAccountPublicKey: string) => { - return encodeKey(flowAccountPublicKey, ECDSA_P256, SHA3_256, 1000) +export enum SignAlgorithm { + ECDSA_P256 = 1, + ECDSA_secp256k1 = 2, + BLS_BLS12_381 = 3, } +const ec = new EC("p256") + const hashMsgHex = (msgHex: string) => { const sha = new SHA3(256) sha.update(Buffer.from(msgHex, "hex")) diff --git a/src/fclConfig.ts b/src/fclConfig.ts index 835f57e..7def0aa 100644 --- a/src/fclConfig.ts +++ b/src/fclConfig.ts @@ -1,16 +1,7 @@ import {config} from "@onflow/fcl" +import flowJSON from "../flow.json" -export default function fclConfig( - flowAccessNode: string, - flowAccountAddress: string, - contractFungibleToken: string, - contractFlowToken: string, - contractFUSD: string -) { - config() - .put("accessNode.api", flowAccessNode) - .put("0xSERVICE", flowAccountAddress) - .put("0xFUNGIBLETOKENADDRESS", contractFungibleToken) - .put("0xFLOWTOKENADDRESS", contractFlowToken) - .put("0xFUSDADDRESS", contractFUSD) +export default function fclConfig(flowAccessNode: string) { + config().put("accessNode.api", flowAccessNode).put("flow.network", "local") + config().load({flowJSON}) } diff --git a/src/harness/cmds/q1.js b/src/harness/cmds/q1.js index a5e9662..71e951d 100644 --- a/src/harness/cmds/q1.js +++ b/src/harness/cmds/q1.js @@ -6,7 +6,7 @@ export const CMD = async () => { // prettier-ignore return query({ cadence: ` - pub fun main(): Int { + access(all) fun main(): Int { return 7 } `, diff --git a/src/harness/cmds/q2.js b/src/harness/cmds/q2.js index f715a32..57a92b2 100644 --- a/src/harness/cmds/q2.js +++ b/src/harness/cmds/q2.js @@ -6,7 +6,7 @@ export const CMD = async () => { // prettier-ignore return query({ cadence: ` - pub fun main(a: Int, b: Int): Int { + access(all) fun main(a: Int, b: Int): Int { return a + b } `, diff --git a/src/init.ts b/src/init.ts index 294a5dd..211fc5f 100644 --- a/src/init.ts +++ b/src/init.ts @@ -5,7 +5,7 @@ import initTransaction from "cadence/transactions/init.cdc" import {accountLabelGenerator} from "src/accountGenerator" import {authz} from "src/authz" import {SERVICE_ACCOUNT_LABEL} from "src/constants" -import {encodeServiceKey} from "src/crypto" +import {HashAlgorithm, SignAlgorithm} from "src/crypto" async function isInitialized(flowAccountAddress: string): Promise { try { @@ -61,7 +61,9 @@ export async function initializeWallet(config: { fcl.transaction(initTransaction), fcl.args([ fcl.arg(FCLContract, t.String), - fcl.arg(encodeServiceKey(flowAccountPublicKey), t.String), + fcl.arg(flowAccountPublicKey, t.String), + fcl.arg(HashAlgorithm.SHA3_256, t.UInt8), + fcl.arg(SignAlgorithm.ECDSA_P256, t.UInt8), fcl.arg(initAccountsLabels, t.Array(t.String)), ]), fcl.proposer(authorization),