# Token Transfer

Token transfer can be done in following way.

```typescript
const depositor = signer.address;
const sourceChain = CHAIN_ID_BSC;

const depositorAddrInSolana = ZebecSolBridgeClient.getProxyUserKey(
   depositor, 
   sourceChain, 
   SOL_ZEBEC_BRIDGE_ADDRESS
);

const tokenAddress = "<evm address of token>";

// use ui value for amount
const amount = "1";

// this may vary depending upon the token being transfered
const relayFee = "0.1";

// transfer from evm to solana
const transferReceipt = await transferEvm(
	signer,
	tokenAddress,
	sourceChain,
	amount,
	targetChain,
	proxyAccount.toString(),
	relayFee,
);
```

*Note: The solana proxy address that is derived from the user's evm address must be initialized beforehand. To initialize see initialize proxy account part.*

After this, it takes some time for your token to reach solana chain. During this time, a vaa is created which is then verified and signed by the wormhole validators called guardians. You can obtain the vaa in following way.

```typescript
const sequence = parseSequenceFromLogEth(transferReceipt, getBridgeAddressForChain(sourceChain));
const transferEmitterAddress = getEmitterAddressEth(getTokenBridgeAddressForChain(sourceChain));
const { vaaBytes } = await getSignedVAAWithRetry(
	WORMHOLE_RPC_HOSTS,
	sourceChain,
	transferEmitterAddress,
	sequence,
);
```

The vaa then can be used to posted on solana chain and redeem the token transferred. Zebec provides specialized token bridge relayer supporting certain tokens as well that automatically relay your tokens using small amount of fee so this part may be *optional*. However, if you want to manually relay you can accomplish it in following way.

```typescript
const payerAddress = wallet.publicKey.toString();
const bridgeAddress = getBridgeAddressForChain(targetChain);

const vaaBuf = Buffer.from(vaaBytes);

setDefaultWasm("node"); // use bundler for browser

// posting vaa in solana
await postVaaSolanaWithRetry(
   connection,
   wallet.signTransaction,
   bridgeAddress,
   payerAddress,
   vaaBuf,
   MAX_VAA_UPLOAD_RETRIES_SOLANA,
);

// redeeming token
const unsignedTransaction = await redeemOnSolana(
	connection,
	bridgeAddress,
	tokenBridgeAddress,
	payerAddress,
	vaaBytes,
);
unsignedTransaction.partialSign(keypair);

const txid = await connection.sendRawTransaction(unsignedTransaction.serialize());
await connection.confirmTransaction(txid);
```

If vaa is supposed to be relayed and token is redeemed by a relayer, in that case you can check and wait for token to be redeemed by the relayer in following way.

```typescript
let success = false;
let retry = 0;

while(!success) {
   success = await getIsTransferCompletedSolana(tokenBridgeAddress, transferVaa, connection);
   await new Promise((r) => setTimeout(r, 5000));	
   if (retry > 13) throw new Error("Transfer failed!");
   retry++;
}

console.log("transfer successful");
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.zebec.io/zebec-bridge/bridge-sdk/deposit/token-transfer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
