deBridge
  • Introduction
  • The deBridge Messaging Protocol
    • Protocol Overview
    • Fees and Supported Chains
    • 🟢Deployed Contracts
    • Development Guides
      • Building an EVM-based dApp
        • EVM smart contract interfaces
          • Interfaces
            • ICallProxy
            • IDeBridgeGate
            • IDeBridgeToken
            • IDeBridgeTokenDeployer
            • IOraclesManager
            • ISignatureVerifier
            • IWethGate
          • Libraries
            • Flags
          • Periphery
            • CallProxy
            • DeBridgeToken
            • DeBridgeTokenProxy
            • SimpleFeeProxy
          • Transfers
            • DeBridgeGate
            • DeBridgeTokenDeployer
            • OraclesManager
            • SignatureVerifier
            • WethGate
      • Sending cross-chain messages from Solana
        • On-Chain external call preparation for Solana
        • Off-chain external call preparation for Solana
      • Lifecycle of a cross-chain call
      • Gathering data for the claim
    • Development Tools
    • Security
    • Slashing and Delegated Staking
  • 🔁DLN: The deBridge Liquidity Network Protocol
    • Introduction
    • Protocol Overview
    • deBridge Hooks
    • Fees and Supported Chains
    • 🟢Deployed Contracts
    • Market and Limit Orders
    • Integration Guidelines
      • Interacting with the API
        • Authentication
        • Creating an Order
          • Quick Start
          • Reserve Assets
          • Bridging Reserve Assets
          • Bridging non-reserve assets
          • API Parameters
            • Estimation-Only
            • prependOperatingExpenses
          • API Response
            • JSON Example
          • Refreshing Estimates
          • Fees and operating expenses
          • Order Fulfillment
            • Detecting the Order
            • Fulfilling the Order
              • Pre-Fill-Swap
            • Claiming the Order
        • Tracking Order Status
          • Order States
        • Integrating deBridge hooks
          • Creating Hook data for Solana
        • Submitting an Order Creation Transaction
        • Cancelling the Order
        • Affiliate fees
      • deBridge Widget
      • Interacting with smart contracts
        • Placing orders
        • Filling orders
        • Withdrawing Affiliate Fees
    • Interacting with the deBridge App
      • Custom Linking
    • Protocol specs
      • Deterministic order ID
      • Hook data
        • Anatomy of a Hook for the EVM-based chains
        • Anatomy of a Hook for Solana
  • 💸dePort
    • Getting started
    • Transfers Flow
  • ⚡deBridge Points
    • Referrers Overview
    • Integrators Overview
  • 🌐deBridge IaaS
    • Getting started
  • 🌐Legal
    • SDK & API License Agreement
  • External Links
    • deBridge Use Cases
      • 💡Examples
    • Talks, Videos, and Articles
    • Website
    • Github
    • Twitter
    • Social channels
      • Discord
      • Facebook
      • LinkedIn
      • Medium
      • Telegram
      • YouTube
Powered by GitBook
On this page
  • 0. Order creation
  • 1. Intro
  • 2. Expenses
  • 2.1. Rewards
  • 3. Pubkey substituion
  • 3.1 Expenses
  • 4. DataSubstitution
  • 5. Calldata serialization

Was this helpful?

  1. DLN: The deBridge Liquidity Network Protocol
  2. Integration Guidelines
  3. Interacting with the API
  4. Integrating deBridge hooks

Creating Hook data for Solana

0. Order creation

Make sure that you're creating order with receiver = exe59FS5cojZkPJVDFDV8RnXCC7wd6yoBjsUtqH7Zai (hex: 0x09b966be097f46dcf58ebaae2365f56b74cd218a2b8c62468ffa4c53d484b053)

This is the program that deserializes calldata, converts it into Solana TransactionInstructions and executes them via CPI.

1. Intro

Solana calldata is a serialized TransactionInstruction list with additional metadata (see next sections). It can be serialized using a wasm module built by deBridge.

After order fulfillment funds are transferred to the AUTHORITY_PLACEHOLDER (in case take token is native sol). When take token is SPL token funds are being transferred to the WALLET_PLACEHOLDER.

During calldata execution (via UI or automatic executor) executor (entity that sends transaction with ExecuteExternalCall instruction) transfers *rewards* amount of native Sol to AUTHORITY_PLACEHOLDER and receives *expenses* amount of take token from WALLET_PLACEHOLDER.

Each calldata instruction is signed by AUTHORITY_PLACEHOLDER during execution, no additional signatures could be passed to the CPI.

2. Expenses

Determine how much lamports your instruction spends on the destination network (most often, for account creation). Record this value as expenses. Each instruction is technically worth 5000 lamports (since we can't determine how many resources it will spend in advance, the implication is that it can be executed in a separate transaction). Therefore, 5000 + expenses is the estimate of how much lamports will cost the execution.

2.1. Rewards

Reward is an amount that covers taker expenses (expenses field) and makes execution of calldata profitable for executor => makes calldata to be executed automatically. Reward for each instruction is deducted from the wallet placeholder amount. Rewards can't be native sol. Rewards are set by the DLN API.

3. Pubkey substituion

Determine which accounts in the instruction are input-dependent and cannot be passed directly from the user for security reasons.

For example, if there is a PDA in the destination network that depends on some unique transfer identifier, then we need to form `PubkeySubstitutions`

3.1 Expenses

As well as pubkey substitutions, placeholders could be used to substitute extcall accounts, but placeholders can't be used to calculate ATA during extcall execution. At the moment we have the following placeholders:

  • ExtcallMetaPlacehoder: 7cu34CRu47UZKLRHjt9kFPhuoYyHCzAafGiGWz83GNFs will be replaced by ExtcallMeta. ExtcallMeta contains such info as order take token, take token amount, execution state, orderId.

If both placeholder and substitution are used for the same account, only substitution will be performed.

4. DataSubstitution

If you need a transfer amount as part of your transfer and it cannot be calculated in advance, then you must use DataSubstitution. One substitution is now available (SubmissionAuthWalletAmount) which works as follows. Takes the account_index account of the current instruction, interprets it as a token account, takes its balance, chooses its encoding (big endian, little endian), uses substration and inserts it into the current instruction by offset before calling it.

5. Calldata serialization

Instructions should be serialized one by one, final calldata is a concatenation of separately serialized instructions.

Solana's TransactionInstructions could be serialized into calldata format using @debridge-finance/debridge-external-call npm package:

Copy

import * as wasm from "@debridge-finance/debridge-external-call";
import { PublicKey, TransactionInstruction } from "@solana/web3.js";

/**
 * Substitutes amount at offset with `walletBalance(accounts[account_index]) - subtraction`
 */
type AmountSubstitution = {
  /**
   * big or little endian
   */
  is_big_endian: boolean;
  /**
   * At what offset substitution should be done
   */
  offset: number;
  /**
   * index of account in TransactionInstruction.keys to get balance for
   */
  account_index: number;
  /**
   * Amount to deduct from wallet balance
   */
  subtraction: number;
};

/**
 * Since we don't know submissionAuth at the moment of calldata preparation we can prepare substitution to replace
 * account at `index` with actual ATA(submissionAuth, tokenMint) during execution
 */
type WalletSubstitution = {
  /**
   * Token mint to calculate ATA for
   */
  token_mint: string;
  /**
   * Account at this index will be replaced with ATA(submissionAuth, tokenMint) during execution
   */
  index: number;
};

/**
 * Structure required by wasm module
 */
interface IExtIx {
  keys: {
    pubkey: string;
    isSigner: boolean;
    isWritable: boolean;
  }[];
  data: Buffer;
  programId: string;
}

function ixToIExtIx(ix: TransactionInstruction): IExtIx {
  return {
    keys: ix.keys.map((meta) => ({
      pubkey: meta.pubkey.toBase58(),
      isSigner: meta.isSigner,
      isWritable: meta.isWritable,
    })),
    programId: ix.programId.toBase58(),
    data: ix.data,
  };
}

function serialize(
  instruction: TransactionInstruction,
  substitutions?: {
    amountSubstitutions?: AmountSubstitution[];
    walletSubstitutions?: WalletSubstitution[];
  },
  expense?: bigint,
  reward?: bigint,
  isInMandatoryBlock: boolean = false,
) {
  const ixWrapper = new wasm.ExternalInstructionWrapper(
    reward,
    expense,
    isInMandatoryBlock,
    substitutions?.amountSubstitutions ?? [],
    substitutions?.walletSubstitutions ?? [],
    ixToIExtIx(instruction),
  );

  return ixWrapper.serialize();
}

const ix1: TransactionInstruction;
const ix2: TransactionInstruction;

const serializedIx1 = serialize(ix1, undefined, 1000n);
const serializedIx2 = serialize(ix2, undefined, 2000n);

const calldata = Buffer.concat([serializedIx1, serializedIx2 /** rest serialized instructions if any */]);
PreviousIntegrating deBridge hooksNextSubmitting an Order Creation Transaction

Last updated 1 month ago

Was this helpful?

Wallet Placeholder: J4vKrc4pCdtiHpxFDfBy4iyZ22Uf7fBjJyJ817k4673y - if you set this pubkey to some account, it will be replaced by actual ExtcallWallet during execution. ExtcallWallet is a that contains order's take tokens (in case take token is an SPL token. When native Sol is used ExtcallWallet will be empty).

Authority Placeholder: 2iBUASRfDHgEkuZ91Lvos5NxwnmiryHrNbWBfEVqHRQZ will be replaced by ExtcallAuthority account during execution. Extcall authority is an owner/authority account for ExtcallWallet. It is this account that manages . When take token of the order is native Sol, funds will be transferred here (not to the ExtcallWallet)

🔁
token account
#2.-expenses