@debridge-finance/solana-contracts-client
TypeScript icon, indicating that this package has built-in type declarations

4.0.6 • Public • Published

Docs

Client init

Since js doesn't support async constructors we have to initialize client object with const client = new DeBridgeSolanaClient() and then wait until it initializes (await client.init()) - loads program state, etc... After initialization we can request data from blockchain and build transactions

How to wrap Sol->WSol (SPL-Sol)

We can't send native SOL tokens, we need to wrap them first into SPL-token form (SystemProgram.createAccount + SystemProgram.transfer native sol to created account + TokenProgram.InitializeAccount to convert system account into token account (SPL-wallet)). If we don't want to create new wallet we can call SystemProgram.transfer and then TokenProgram.SyncNative to convert transferred Sols into SPL-Sol

How to send token from Solana to other blockchain?

  1. Check if user's associated wallet exists and user have ehough tokens. We can get all user's wallets with getAllWalletsWithBalances
  2. Check if chain is supported - we can't send from Solana to unsupported chains, hence chainSupportInfo must exist and be in Supported state, see getChainSupportInfoSafe for details
  3. Check if bridge exists (SPL-tokens are sent via Send bridge, deAssets are sent via Mint bridge which 100% exists) and in Working state - if bridge doesn't exist we can't send tokens and we need to init bridge first (see bridge initialization->send). We can check if bridge exists with getBridgeByDeBridgeId
  4. [Optional] If we want to pay fee with asset we're sending, we need to set useAssetFee flag to true and check if bridgeFeeInfo exists using isBridgeFeeInfoInitialized. If bridgeFeeInfo->assetChainFee not exists we can't pay fee with assets and we also can't init bridgeFeeInfo.
  5. [Optional] If we want to pass some additional data (external call data) we have two options - set SEND_HASHED flag and pass external call data off-chain (saves gas but automatic execution is unavailable) or save external call data into special Solana account (ExternalCallStorage) associated with send transaction
    • ExtCallShortcut flow - we need to pass external call shortcut (keccak256(ext call data)) and flags with 4th bit (8) set to send->submissionParams
    • ExtCallStorage flow - see externall call preparation section
  6. Send! If we have a discount we want to pass it into send instruction, else we need to pass speical no_discount account (but buildSendInstruction calculates all the accounts under the hood). We also need to specify which wallet we want to use (user may have multiple wallets associated with same token mint), execution fee is a reward for automatic claim in target chain

How to claim token from other blockchain to Solana

  1. Check if chain is supported - we can't claim from unsupported chains, hence chainSupportInfo must exist and be in Supported state, see getChainSupportInfoSafe for details
  2. Check if bridge exists - getBridgeByDeBridgeId (deAssets are claimed via Send bridge, assets are claimed via Mint) and in Working state - if bridge doesn't exist we can't send tokens and we need to init bridge first (see bridge initialization->mint).
  3. Check if submission wasn't already claimed with isSubmissionUsed
  4. Store confirmations from validators with storeConfirmations instruction (one transaction can store up to 6 signatures) which can be built with buildStoreSignaturesTransaction, this transactions can be signed and sent in a batch mode.
  5. [Optional] If we have external call data we need to check if SEND_HASHED_FLAG is set. If flag is not set we need to fill ExternalCallStorage
  6. All checks from steps 1,2 and 3 can be performed in automatic mode with function checkClaimParams - check if submission is not already claimed, check bridge balance, check chainSupportInfo and Bridge.
  7. Claim! just call claim instruction built with buildClaimTransaction after all signatures were saved - this can be checked with isTransactionConfirmed or getConfirmationsCount
  8. [Optional] if external call exists, we need to execute it, we could execute them by calling buildOptimalExecuteExternalCallTransaction. This function tries to build tx with execution of as much as possible external instructions. Need to be called until external call is executed or fails to execute.

External call data preparation

Since solana's transaction size limit is 1232 bytes we can't store all external call data in single transaction, hence we need to split the data in chunks and send bunch of chunks in different transactions. We need to call initExternalCallStorage instruction (storageKey = external call shortcut - claim/extCallShortcut - send, external call length = external call data length, source chain id = source chain - claim/solana id - send) to allocate memory and fill first chunk. If external call data is larger than ~800 bytes, we need to initialize externall call storage and fill it with data calling extendExternalCallStorage instruction buildExtendExternalCallStorageInstruction.

Function prepareExtCallTransactions splits data into chunks of optimal size and returns array of transactions to execute. First tx is initExternalCallStorage, rest (optional) are extendExternalCallStorage. initExternalCallStorage allocates required memory space in blockchain and fills it with initial data chunk. Since we can't write data to not-yet-allocated memory we have to wait until first transaction is finalized and extCallStorage is allocated. After that we can send rest transactions in a batch mode and wait until Solana processes them. We can check if storage was filled correctly using isExtCallStorageCorrect

Bridge initialization

  • Send bridge - to init send bridge we need to call initializeSendBridge instruction for SPL-token mint that we want to init - buildInitializeSendBridgeTransaction.
  • Mint bridge - to init mint bridge we need to storeConfirmations for deploy info, wait until confirmations are saved and then call initializeMintBridge instruction - buildInitializeMintBridgeTransaction

Entities

  • State - unique, contains oracles, required oracles, min confirmations, if protocol is active and other system information.
  • Bridge (general info) - contains bridge state (working/paused), collected fee and other system information.
  • Send bridge - assocated with token, contains amount of locked tokens, native SPL-token address and general bridge info
  • Mint bridge - associated with token in outter chain and outer chain id, contains amount of minted tokens, source chain id, source token address and general bridge info
  • ChainSupportInfo - associated with chain, contains State (supported/unsupported) of target chain and fixedFee/transferFee values (if values are None globalFixedFee/globalTransferFee will be used)
  • BridgeFeeInfo - associated with bridge, contains assetChainFee option (None or value, if None asset chain fee is unsupported)

Claim flow (with ext call) with affected accounts (Assuming that submission wasn't claimed, bridge/state/chainSupportInfo exists)

Action Initialized accounts Updated Accounts Closed Accounts Comments
storeConfirmations [confirmationStorage] confirmationStorage store signatures into confirmationStorage, account is created if not exists yet
initExternalCallStorage externalCallStorage, externalCallMeta allocate externall call storage, set externalCallMeta = accumulation
updateExternalCallStorage externalCallStorage, externalCallMeta fill external call storage with data, set externalCallMeta = accumulation
claim submission, [stakingWallet], [payerWallet], [claimToWallet] bridge, stakingWallet, payerWallet, claimToWallet confirmationStorage create submission account, close confirmation storage, set externalCallMeta state = execution, update bridge locked/minted amount, move funds to/from wallets
executeExternalCall externalCallMeta externalCallStorage set externalCallMeta = executed, close external call storage

Claim flow (without ext call) with affected accounts (Assuming that submission wasn't claimed, bridge/state/chainSupportInfo exists)

Action Initialized accounts Updated Accounts Closed Accounts Comments
storeConfirmations [confirmationStorage] confirmationStorage store signatures into confirmationStorage, account is created if not exists yet
claim submission, [stakingWallet], [payerWallet], [claimToWallet] bridge, stakingWallet, payerWallet, claimToWallet confirmationStorage create submission account, close confirmation storage, update bridge locked/minted amount, move funds to/from wallets

Examples

send and claim exmaples

Claim flow

sendClaim-Page-1 drawio

Send flow

sendClaim-Page-2 drawio

Package Sidebar

Install

npm i @debridge-finance/solana-contracts-client

Weekly Downloads

457

Version

4.0.6

License

GPL-3.0-only

Unpacked Size

1.94 MB

Total Files

185

Last publish

Collaborators

  • de_totoro
  • alexsmirnov
  • artyukh
  • alexeychr