github.com/DapperCollectives/CAST/backend@v0.0.0-20230921221157-1350c8be7c96/main/cadence/scripts/get_total_balance.cdc (about)

     1  import FlowStorageFees from 0xe467b9dd11fa00df
     2  import FungibleToken from 0xf233dcee88fe0abe
     3  import FlowToken from 0x1654653399040a61
     4  import FlowIDTableStaking from 0x8624b52f9ddcd04a
     5  import LockedTokens from 0x8d0e87b65159ae63
     6  import FlowStakingCollection from 0x8d0e87b65159ae63
     7  
     8  // This script gets the TOTAL number of FLOW an account owns, across unlocked, locked, and staking.
     9  
    10  // Adds up these numbers:
    11  
    12  // tokens in normal account
    13  // tokens in normal account staking
    14  // tokens in normal account delegating
    15  // tokens in shared account
    16  // tokens in shared account staking
    17  // tokens in shared account delegating
    18  
    19  pub struct AccountInfo {
    20      pub(set) var primaryAcctBalance: UFix64
    21      pub(set) var secondaryAddress: Address?
    22      pub(set) var secondaryAcctBalance: UFix64
    23      pub(set) var stakedBalance: UFix64
    24      pub(set) var hasVault: Bool
    25      pub(set) var stakes: String
    26  
    27      init() {
    28          self.primaryAcctBalance = 0.0 as UFix64
    29          self.secondaryAddress = nil
    30          self.secondaryAcctBalance = 0.0 as UFix64
    31          self.stakedBalance = 0.0 as UFix64
    32          self.hasVault = true
    33          self.stakes = ""
    34      }
    35  }
    36  
    37  pub fun getStakesAndDelegations(_ account: PublicAccount) : {String:UFix64} {
    38      
    39      var allNodeInfo: [FlowIDTableStaking.NodeInfo] = []
    40      var allDelegateInfo: [FlowIDTableStaking.DelegatorInfo] = []
    41      
    42      // ====== Get account stake - Old Way =====
    43      let nodeStakerCap = account.getCapability<&{FlowIDTableStaking.NodeStakerPublic}>(
    44          FlowIDTableStaking.NodeStakerPublicPath)
    45      if let nodeStakerRef = nodeStakerCap.borrow() {
    46          let nodeInfo = FlowIDTableStaking.NodeInfo(nodeID: nodeStakerRef.id)
    47          allNodeInfo.append(nodeInfo)
    48      }
    49  
    50      // ====== Get account delegation - Old Way =====
    51      let delegatorCap = account.getCapability<&{FlowIDTableStaking.NodeDelegatorPublic}>(
    52          /public/flowStakingDelegator)
    53      if let delegatorRef = delegatorCap.borrow() {
    54          let delegatorInfo = FlowIDTableStaking.DelegatorInfo(
    55              nodeID: delegatorRef.nodeID,
    56              delegatorID: delegatorRef.id
    57          )
    58          allDelegateInfo.append(delegatorInfo)
    59      }
    60  
    61      // ====== Get account stakes and delegations =====
    62      var doesAccountHaveStakingCollection = FlowStakingCollection.doesAccountHaveStakingCollection(address: account.address)
    63      if doesAccountHaveStakingCollection {
    64          allNodeInfo.appendAll(FlowStakingCollection.getAllNodeInfo(address: account.address))
    65          allDelegateInfo.appendAll(FlowStakingCollection.getAllDelegatorInfo(address: account.address))
    66      }
    67  
    68      // ====== Shared account =====
    69      let lockedAccountInfoCap = account
    70          .getCapability<&LockedTokens.TokenHolder{LockedTokens.LockedAccountInfo}>(
    71              LockedTokens.LockedAccountInfoPublicPath)
    72      if let lockedAccountInfoRef = lockedAccountInfoCap.borrow()  {
    73          // ====== Get shared account stake - Old Way =====
    74          if let nodeID = lockedAccountInfoRef.getNodeID() {
    75              let nodeInfo = FlowIDTableStaking.NodeInfo(nodeID: nodeID)
    76              allNodeInfo.append(nodeInfo)
    77          }
    78  
    79          // ====== Get shared account delegation - Old Way =====
    80          if let delegatorID = lockedAccountInfoRef.getDelegatorID() {
    81              if let nodeID = lockedAccountInfoRef.getDelegatorNodeID() {
    82                  let delegatorInfo = FlowIDTableStaking.DelegatorInfo(nodeID: nodeID, delegatorID: delegatorID)
    83                  allDelegateInfo.append(delegatorInfo)
    84              }
    85          }
    86  
    87          // ====== Get shared account stakes and delegations =====
    88          doesAccountHaveStakingCollection = FlowStakingCollection.doesAccountHaveStakingCollection(address: lockedAccountInfoRef.getLockedAccountAddress())
    89          if doesAccountHaveStakingCollection {
    90              allNodeInfo.appendAll(FlowStakingCollection.getAllNodeInfo(address: lockedAccountInfoRef.getLockedAccountAddress()))
    91              allDelegateInfo.appendAll(FlowStakingCollection.getAllDelegatorInfo(address: lockedAccountInfoRef.getLockedAccountAddress()))
    92          }
    93      }
    94  
    95      // ===== Aggregate all stakes and delegations in a digestible set =====
    96      // deduplication between the old way and the new way will happen automatically because the result is stored in a map
    97      let stakes : {String:UFix64} = {}
    98      for nodeInfo in allNodeInfo {
    99          let balance =  nodeInfo.tokensStaked
   100                          + nodeInfo.tokensCommitted
   101                          + nodeInfo.tokensUnstaking
   102                          + nodeInfo.tokensUnstaked
   103                          + nodeInfo.tokensRewarded
   104  
   105          stakes["n:".concat(nodeInfo.id)] = balance
   106      }
   107  
   108      for delegatorInfo in  allDelegateInfo {
   109          let balance =  delegatorInfo.tokensStaked
   110                          + delegatorInfo.tokensCommitted
   111                          + delegatorInfo.tokensUnstaking
   112                          + delegatorInfo.tokensUnstaked
   113                          + delegatorInfo.tokensRewarded
   114          
   115          stakes["n:".concat(delegatorInfo.nodeID).concat(" d:").concat(delegatorInfo.id.toString())] = balance
   116      }
   117  
   118      return stakes
   119  }
   120  
   121  
   122  pub fun main(address: Address): [AnyStruct] {
   123          var info: AccountInfo = AccountInfo()
   124  
   125          let account = getAccount(address)
   126  
   127          // If the account is an unlocked account, lets collect its balances
   128          if account.getLinkTarget(/public/lockedFlowTokenReceiver) == nil {
   129              info.hasVault = true
   130  
   131              if account.storageUsed > 0 as UInt64 {
   132                  // Get the primary/normal account balance (unlocked tokens)
   133                  if let vaultRef = account.getCapability(/public/flowTokenBalance)
   134                      .borrow<&FlowToken.Vault{FungibleToken.Balance}>(){
   135                      info.primaryAcctBalance = vaultRef.balance
   136                  }
   137                  // Accounts 0xf8ded0f117ba2462 and 0x3112dbb9973ff3ad have the same locked account 0x1cb9692c064024bd and the same stake id.
   138                  // This is expected, this was made manually. 0xf8ded0f117ba2462 has all keys revoked, and is safe to skip.
   139                  if account.address != 0xf8ded0f117ba2462 {
   140  
   141                      let lockedAccountInfoCap = account
   142                          .getCapability<&LockedTokens.TokenHolder{LockedTokens.LockedAccountInfo}>(
   143                              LockedTokens.LockedAccountInfoPublicPath)
   144  
   145                      // Get secondary/locked account address and balance
   146                      if let lockedAccountInfoRef = lockedAccountInfoCap.borrow() {
   147                          info.secondaryAddress = lockedAccountInfoRef.getLockedAccountAddress() as Address?
   148                          // `+ FlowStorageFees.minimumStorageReservation` is due to https://github.com/onflow/flow-core-contracts/blob/6fcd492d16186e5615d2e6589bc5b7ebce41f548/contracts/LockedTokens.cdc#L308
   149                          info.secondaryAcctBalance = lockedAccountInfoRef.getLockedAccountBalance() + FlowStorageFees.minimumStorageReservation
   150                      }
   151                  
   152                      // Get stakes and delegations of the account and secondary/locked account
   153                      let stakes = getStakesAndDelegations(account)
   154  
   155                      var stakeKey = ""
   156                      for key in stakes.keys {
   157                          let value = stakes[key]!
   158                          stakeKey = stakeKey.concat(key).concat(", ")
   159                          info.stakedBalance = info.stakedBalance + value
   160                      }
   161                      info.stakes = stakeKey
   162                  }
   163              } else {
   164                  info.hasVault = false
   165              }
   166          }
   167  
   168      return [info.primaryAcctBalance, info.secondaryAcctBalance, info.stakedBalance]
   169  }