import { sha256 } from "@noble/hashes/sha2";
import { signMessage } from "@dynamic-labs-sdk/client";
import bs58 from "bs58";
async function sendNearTransfer(
recipient: string,
amountNear: number,
nearAddress: string,
solWallet: WalletAccount,
): Promise<string> {
const pubkey = bs58.decode(solWallet.address);
// Convert NEAR to yoctoNEAR (1 NEAR = 10^24 yoctoNEAR)
const [wholePart, fracPart = ""] = amountNear.toString().split(".");
const paddedFrac = fracPart.padEnd(24, "0").slice(0, 24);
const amountYocto = BigInt(wholePart + paddedFrac);
// Fetch access key and recent block hash
const [accessKeyResult, blockResult] = await Promise.all([
nearRpc("query", {
request_type: "view_access_key",
finality: "final",
account_id: nearAddress,
public_key: `ed25519:${bs58.encode(pubkey)}`,
}),
nearRpc("block", { finality: "final" }),
]);
const nonce = BigInt(accessKeyResult.nonce) + BigInt(1);
const blockHash = bs58.decode(blockResult.header.hash);
// Build transfer action: variant 3 (Transfer) + u128 amount
const transferAction = concatBytes(
borshU8(3), // Transfer action variant
borshU128(amountYocto),
);
// Serialize the transaction
const txBytes = concatBytes(
borshString(nearAddress), // signer_id
borshU8(0), // PublicKey variant: ed25519
pubkey, // 32-byte pubkey
borshU64(nonce),
borshString(recipient), // receiver_id
blockHash, // 32-byte block hash
borshU32(1), // number of actions
transferAction,
);
// Hash and sign
const txHash = sha256(txBytes);
const signResult = await signMessage({
walletAccount: solWallet,
message: bytesToHex(txHash),
});
const sigBytes = decodeSig(signResult.signature);
// Build signed transaction
const signedTxBytes = concatBytes(
txBytes,
borshU8(0), // Signature variant: ed25519
sigBytes, // 64-byte signature
);
// Base64 encode and submit
const signedTxBase64 = btoa(String.fromCharCode(...signedTxBytes));
const result = await nearRpc("broadcast_tx_commit", [signedTxBase64]);
return result.transaction.hash;
}