@avalanche-sdk/client
Version:
A TypeScript SDK for interacting with the Avalanche network through JSON-RPC APIs. This SDK provides a comprehensive set of tools to interact with all Avalanche chains (P-Chain, X-Chain, C-Chain) and various APIs, including wallet functionality for transa
696 lines (652 loc) • 21.4 kB
text/typescript
import { createTransport, EIP1193RequestFn } from "viem";
import { describe, expect, test, vi } from "vitest";
import { avalanche } from "../../chains/index.js";
import { createAvalancheBaseClient } from "../createAvalancheBaseClient.js";
import { avalancheActions } from "./avalanche.js";
const mockTransport = () =>
createTransport({
key: "mock",
name: "Mock Transport",
request: vi.fn(async ({ method }) => {
switch (method) {
// P-Chain methods
case "platform.getBalance":
return {
balance: 1,
unlocked: 1,
lockedStakeable: 1,
lockedNotStakeable: 1,
utxoIDs: [{ txID: "string", outputIndex: 1 }],
};
case "platform.getHeight":
return { height: 12345 };
case "platform.getCurrentValidators":
return { validators: [] };
case "platform.getMinStake":
return {
minValidatorStake: 1,
minDelegatorStake: 1,
};
case "platform.getTxStatus":
return { status: "Accepted" };
case "platform.issueTx":
return {
txID: "2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
};
// C-Chain methods
case "avax.getAtomicTx":
return {
tx: "0x00000009de31b4d8b22991d51aa6aa1fc733f23a851a8c9400000000000186a0000000005f041280000000005f9ca900000030390000000000000001fceda8f90fcb5d30614b99d79fc4baa29307762668f16eb0259a57c2d3b78c875c86ec2045792d4df2d926c40f829196e0bb97ee697af71f5b0a966dabff749634c8b729855e937715b0e44303fd1014daedc752006011b730",
blockHeight: "12345",
encoding: "hex",
};
case "avax.getAtomicTxStatus":
return {
status: "Accepted",
blockHeight: "12345",
};
case "avax.getUTXOs":
return {
numFetched: 2,
utxos: [
"0x00000009de31b4d8b22991d51aa6aa1fc733f23a851a8c9400000000000186a0000000005f041280000000005f9ca900000030390000000000000001fceda8f90fcb5d30614b99d79fc4baa29307762668f16eb0259a57c2d3b78c875c86ec2045792d4df2d926c40f829196e0bb97ee697af71f5b0a966dabff749634c8b729855e937715b0e44303fd1014daedc752006011b730",
],
endIndex: {
address: "X-avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy",
utxo: "0x00000009de31b4d8b22991d51aa6aa1fc733f23a851a8c9400000000000186a0000000005f041280000000005f9ca900000030390000000000000001fceda8f90fcb5d30614b99d79fc4baa29307762668f16eb0259a57c2d3b78c875c86ec2045792d4df2d926c40f829196e0bb97ee697af71f5b0a966dabff749634c8b729855e937715b0e44303fd1014daedc752006011b730",
},
};
// X-Chain methods
case "avm.getAllBalances":
return {
balances: [
{
assetID: "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
balance: 1000000000n,
},
],
};
case "avm.getBalance":
return {
balance: 1000000000n,
utxoIDs: [
{
txID: "2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
outputIndex: 0,
},
],
};
case "avm.getHeight":
return { height: 12345 };
case "avm.getTxStatus":
return { status: "Accepted" };
case "avm.issueTx":
return {
txID: "2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
};
// Admin API methods
case "admin.getChainAliases":
return {
aliases: ["myBlockchainAlias", "anotherAlias"],
};
case "admin.getLoggerLevel":
return {
loggerLevels: {
C: {
logLevel: "INFO",
displayLevel: "INFO",
},
},
};
case "admin.loadVMs":
return {
newVMs: {
rWmY6Sh7P9mjQoTfXd89un7WoroFezFXp: ["vm1", "vm2"],
},
failedVMs: {
failedVM1: "Failed to load: missing dependencies",
},
};
// Info API methods
case "info.getNetworkID":
return { networkID: "1" };
case "info.getNetworkName":
return { networkName: "Mainnet" };
case "info.getNodeVersion":
return {
version: "v1.10.0",
databaseVersion: "v1.4.5",
gitCommit: "abcdef1234567890",
vmVersions: {
avm: "v1.10.0",
evm: "v0.12.0",
platform: "v1.10.0",
},
};
case "info.isBootstrapped":
return { isBootstrapped: true };
// Health API methods
case "health.health":
return {
healthy: true,
checks: {
C: {
message: {
engine: {
consensus: {
lastAcceptedHeight: 12345,
lastAcceptedID:
"2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
longestProcessingBlock:
"2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
processingBlocks: 5,
},
vm: null,
},
networking: {
percentConnected: 95.5,
},
},
timestamp: "2024-01-01T00:00:00Z",
duration: 100,
},
},
};
case "health.liveness":
return { healthy: true };
// Index API methods
case "index.getContainerByID":
return {
id: "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY",
bytes:
"0x00000009de31b4d8b22991d51aa6aa1fc733f23a851a8c9400000000000186a0000000005f041280000000005f9ca900000030390000000000000001fceda8f90fcb5d30614b99d79fc4baa29307762668f16eb0259a57c2d3b78c875c86ec2045792d4df2d926c40f829196e0bb97ee697af71f5b0a966dabff749634c8b729855e937715b0e44303fd1014daedc752006011b730",
timestamp: "2024-01-01T00:00:00Z",
encoding: "hex",
index: "12345",
};
case "index.isAccepted":
return { accepted: true, encoding: "hex" };
// Avalanche Public methods
case "eth_baseFee":
return "0x3b9aca00";
case "eth_getChainConfig":
return {
chainId: 43114,
homesteadBlock: 0,
daoForkBlock: 0,
daoForkSupport: true,
eip150Block: 0,
eip150Hash:
"0x0000000000000000000000000000000000000000000000000000000000000000",
eip155Block: 0,
eip158Block: 0,
byzantiumBlock: 0,
constantinopleBlock: 0,
petersburgBlock: 0,
istanbulBlock: 0,
muirGlacierBlock: 0,
apricotPhase1BlockTimestamp: 1640995200,
apricotPhase2BlockTimestamp: 1640995200,
apricotPhase3BlockTimestamp: 1640995200,
apricotPhase4BlockTimestamp: 1640995200,
apricotPhase5BlockTimestamp: 1640995200,
};
case "eth_maxPriorityFeePerGas":
return "0x59682f00";
case "eth_feeConfig":
return {
feeConfig: {
gasLimit: "0x1c9c380",
targetBlockRate: "0x2",
minBaseFee: "0x1",
targetGas: "0x1c9c380",
baseFeeChangeDenominator: "0x8",
minBlockGasCost: "0x0",
maxBlockGasCost: "0x1000000",
blockGasCostStep: "0x100000",
},
lastChangedAt: "0x61e8c8c0",
};
case "eth_getActiveRulesAt":
return {
ethRules: {
"EIP-155": true,
"EIP-158": true,
"EIP-1559": true,
},
avalancheRules: {
"AVALANCHE-1": true,
"AVALANCHE-2": true,
},
precompiles: {
"0x0000000000000000000000000000000000000001": {
name: "ecrecover",
gas: 3000,
},
},
};
default:
return {
result: {
someKey: 1,
},
};
}
}) as unknown as EIP1193RequestFn,
type: "mock",
});
// Create a mock client with all the necessary chain clients
const mockClient = {
...createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
pChain: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
cChain: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
xChain: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
admin: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
info: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
health: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
indexPChainBlock: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
indexCChainBlock: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
indexXChainBlock: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
indexXChainTx: createAvalancheBaseClient({
chain: avalanche,
transport: mockTransport,
}),
} as any;
const avalancheClient = avalancheActions(mockClient);
test("default", async () => {
expect(avalancheClient).toMatchInlineSnapshot(`{
"admin": {
"alias": [Function],
"aliasChain": [Function],
"getChainAliases": [Function],
"getLoggerLevel": [Function],
"loadVMs": [Function],
"lockProfile": [Function],
"memoryProfile": [Function],
"setLoggerLevel": [Function],
"startCPUProfiler": [Function],
"stopCPUProfiler": [Function],
},
"baseFee": [Function],
"cChain": {
"getAtomicTx": [Function],
"getAtomicTxStatus": [Function],
"getUTXOs": [Function],
"issueTx": [Function],
},
"call": [Function],
"createAccessList": [Function],
"createBlockFilter": [Function],
"createContractEventFilter": [Function],
"createEventFilter": [Function],
"createPendingTransactionFilter": [Function],
"estimateContractGas": [Function],
"estimateFeesPerGas": [Function],
"estimateGas": [Function],
"estimateMaxPriorityFeePerGas": [Function],
"feeConfig": [Function],
"getActiveRulesAt": [Function],
"getBalance": [Function],
"getBlobBaseFee": [Function],
"getBlock": [Function],
"getBlockNumber": [Function],
"getBlockTransactionCount": [Function],
"getBytecode": [Function],
"getChainConfig": [Function],
"getChainId": [Function],
"getCode": [Function],
"getContractEvents": [Function],
"getEip712Domain": [Function],
"getEnsAddress": [Function],
"getEnsAvatar": [Function],
"getEnsName": [Function],
"getEnsResolver": [Function],
"getEnsText": [Function],
"getFeeHistory": [Function],
"getFilterChanges": [Function],
"getFilterLogs": [Function],
"getGasPrice": [Function],
"getLogs": [Function],
"getProof": [Function],
"getStorageAt": [Function],
"getTransaction": [Function],
"getTransactionConfirmations": [Function],
"getTransactionCount": [Function],
"getTransactionReceipt": [Function],
"health": {
"health": [Function],
"liveness": [Function],
"readiness": [Function],
},
"indexCChainBlock": {
"getContainerByID": [Function],
"getContainerByIndex": [Function],
"getContainerRange": [Function],
"getIndex": [Function],
"getLastAccepted": [Function],
"isAccepted": [Function],
},
"indexPChainBlock": {
"getContainerByID": [Function],
"getContainerByIndex": [Function],
"getContainerRange": [Function],
"getIndex": [Function],
"getLastAccepted": [Function],
"isAccepted": [Function],
},
"indexXChainBlock": {
"getContainerByID": [Function],
"getContainerByIndex": [Function],
"getContainerRange": [Function],
"getIndex": [Function],
"getLastAccepted": [Function],
"isAccepted": [Function],
},
"indexXChainTx": {
"getContainerByID": [Function],
"getContainerByIndex": [Function],
"getContainerRange": [Function],
"getIndex": [Function],
"getLastAccepted": [Function],
"isAccepted": [Function],
},
"info": {
"acps": [Function],
"getBlockchainID": [Function],
"getNetworkID": [Function],
"getNetworkName": [Function],
"getNodeID": [Function],
"getNodeIP": [Function],
"getNodeVersion": [Function],
"getTxFee": [Function],
"getVMs": [Function],
"isBootstrapped": [Function],
"peers": [Function],
"upgrades": [Function],
"uptime": [Function],
},
"maxPriorityFeePerGas": [Function],
"multicall": [Function],
"pChain": {
"getBalance": [Function],
"getBlock": [Function],
"getBlockByHeight": [Function],
"getBlockchainStatus": [Function],
"getBlockchains": [Function],
"getCurrentSupply": [Function],
"getCurrentValidators": [Function],
"getFeeConfig": [Function],
"getFeeState": [Function],
"getHeight": [Function],
"getL1Validator": [Function],
"getMinStake": [Function],
"getProposedHeight": [Function],
"getRewardUTXOs": [Function],
"getStake": [Function],
"getStakingAssetID": [Function],
"getSubnet": [Function],
"getSubnets": [Function],
"getTimestamp": [Function],
"getTotalStake": [Function],
"getTx": [Function],
"getTxStatus": [Function],
"getUTXOs": [Function],
"getValidatorsAt": [Function],
"issueTx": [Function],
"sampleValidators": [Function],
"validatedBy": [Function],
"validates": [Function],
},
"prepareTransactionRequest": [Function],
"readContract": [Function],
"sendRawTransaction": [Function],
"simulate": [Function],
"simulateBlocks": [Function],
"simulateCalls": [Function],
"simulateContract": [Function],
"uninstallFilter": [Function],
"verifyMessage": [Function],
"verifySiweMessage": [Function],
"verifyTypedData": [Function],
"waitForTransactionReceipt": [Function],
"watchBlockNumber": [Function],
"watchBlocks": [Function],
"watchContractEvent": [Function],
"watchEvent": [Function],
"watchPendingTransactions": [Function],
"xChain": {
"buildGenesis": [Function],
"getAllBalances": [Function],
"getAssetDescription": [Function],
"getBalance": [Function],
"getBlock": [Function],
"getBlockByHeight": [Function],
"getHeight": [Function],
"getTx": [Function],
"getTxFee": [Function],
"getTxStatus": [Function],
"getUTXOs": [Function],
"issueTx": [Function],
},
}`);
});
describe("smoke test", () => {
describe("P-Chain methods", () => {
test("getBalance", async () => {
const res = await avalancheClient.pChain!.getBalance({
addresses: ["P-avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"],
});
expect(res).toBeDefined();
});
test("getHeight", async () => {
const res = await avalancheClient.pChain!.getHeight();
expect(res).toBeDefined();
});
test("getCurrentValidators", async () => {
const res = await avalancheClient.pChain!.getCurrentValidators({
subnetID: "11111111111111111111111111111111LpoYY",
});
expect(res).toBeDefined();
});
test("getMinStake", async () => {
const res = await avalancheClient.pChain!.getMinStake({
subnetID: "11111111111111111111111111111111LpoYY",
});
expect(res).toBeDefined();
});
test("getTxStatus", async () => {
const res = await avalancheClient.pChain!.getTxStatus({
txID: "2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
});
expect(res).toBeDefined();
});
test("issueTx", async () => {
const res = await avalancheClient.pChain!.issueTx({
tx: "0x..",
encoding: "hex",
});
expect(res).toBeDefined();
});
});
describe("C-Chain methods", () => {
test("getAtomicTx", async () => {
const res = await avalancheClient.cChain!.getAtomicTx({
txID: "2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
});
expect(res).toBeDefined();
});
test("getAtomicTxStatus", async () => {
const res = await avalancheClient.cChain!.getAtomicTxStatus({
txID: "2QouvMUbQ6oy7yQ9tLvL3L8tGQG2QK1wJ1q1wJ1q1wJ1q1wJ1q1wJ1q1wJ1",
});
expect(res).toBeDefined();
});
test("getUTXOs", async () => {
const res = await avalancheClient.cChain!.getUTXOs({
addresses: ["X-avax1tnuesf6cqwnjw7fxjyk7lhch0vhf0v95wj5jvy"],
});
expect(res).toBeDefined();
});
test("issueTx", async () => {
const res = await avalancheClient.cChain!.issueTx({
tx: "0x..",
encoding: "hex",
});
expect(res).toBeDefined();
});
});
describe("X-Chain methods", () => {
test("getAllBalances", async () => {
const res = await avalancheClient.xChain!.getAllBalances({
addresses: ["X-avax18jma8ppw3nhx5r4ap8clazz0dps7rv5ukulre5"],
});
expect(res).toBeDefined();
});
test("getBalance", async () => {
const res = await avalancheClient.xChain!.getBalance({
address: "X-avax18jma8ppw3nhx5r4ap8clazz0dps7rv5ukulre5",
assetID: "FvwEAhmxKfeiG8SnEvq42hc6whRyY3EFYAvebMqDNDGCgxN5Z",
});
expect(res).toBeDefined();
});
test("getHeight", async () => {
const res = await avalancheClient.xChain!.getHeight();
expect(res).toBeDefined();
});
test("getTxStatus", async () => {
const res = await avalancheClient.xChain!.getTxStatus({
txID: "11111111111111111111111111111111LpoYY",
});
expect(res).toBeDefined();
});
test("issueTx", async () => {
const res = await avalancheClient.xChain!.issueTx({
tx: "0x..",
encoding: "hex",
});
expect(res).toBeDefined();
});
});
describe("Admin API methods", () => {
test("getChainAliases", async () => {
const res = await avalancheClient.admin!.getChainAliases({
chain: "sV6o671RtkGBcno1FiaDbVcFv2sG5aVXMZYzKdP4VQAWmJQnM",
});
expect(res).toBeDefined();
});
test("getLoggerLevel", async () => {
const res = await avalancheClient.admin!.getLoggerLevel({
loggerName: "C",
});
expect(res).toBeDefined();
});
test("loadVMs", async () => {
const res = await avalancheClient.admin!.loadVMs();
expect(res).toBeDefined();
});
});
describe("Info API methods", () => {
test("getNetworkID", async () => {
const res = await avalancheClient.info!.getNetworkID();
expect(res).toBeDefined();
});
test("getNetworkName", async () => {
const res = await avalancheClient.info!.getNetworkName();
expect(res).toBeDefined();
});
test("getNodeVersion", async () => {
const res = await avalancheClient.info!.getNodeVersion();
expect(res).toBeDefined();
});
test("isBootstrapped", async () => {
const res = await avalancheClient.info!.isBootstrapped({
chain: "X",
});
expect(res).toBeDefined();
});
});
describe("Health API methods", () => {
test("health", async () => {
const res = await avalancheClient.health!.health({
tags: ["11111111111111111111111111111111LpoYY"],
});
expect(res).toBeDefined();
});
test("liveness", async () => {
const res = await avalancheClient.health!.liveness();
expect(res).toBeDefined();
});
});
describe("Index API methods", () => {
test("getContainerByID", async () => {
const res = await avalancheClient.indexPChainBlock!.getContainerByID({
id: "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY",
encoding: "hex",
});
expect(res).toBeDefined();
});
test("isAccepted", async () => {
const res = await avalancheClient.indexPChainBlock!.isAccepted({
id: "6fXf5hncR8LXvwtM8iezFQBpK5cubV6y1dWgpJCcNyzGB1EzY",
encoding: "hex",
});
expect(res).toBeDefined();
});
});
describe("Avalanche Public methods", () => {
test("baseFee", async () => {
const res = await avalancheClient.baseFee();
expect(res).toBeDefined();
});
test("getChainConfig", async () => {
const res = await avalancheClient.getChainConfig();
expect(res).toBeDefined();
});
test("maxPriorityFeePerGas", async () => {
const res = await avalancheClient.maxPriorityFeePerGas();
expect(res).toBeDefined();
});
test("feeConfig", async () => {
const res = await avalancheClient.feeConfig({
blk: "0x1",
});
expect(res).toBeDefined();
});
test("getActiveRulesAt", async () => {
const res = await avalancheClient.getActiveRulesAt({
timestamp: "0x61e8c8c0",
});
expect(res).toBeDefined();
});
});
});