@ledgerhq/coin-sui 0.9.0 → 0.10.0-nightly.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.unimportedrc.json +1 -1
- package/CHANGELOG.md +26 -0
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.integration.test.js +21 -2
- package/lib/api/index.integration.test.js.map +1 -1
- package/lib/api/index.js +2 -0
- package/lib/api/index.js.map +1 -1
- package/lib/api/index.test.js +37 -0
- package/lib/api/index.test.js.map +1 -1
- package/lib/bridge/buildTransaction.d.ts +1 -3
- package/lib/bridge/buildTransaction.d.ts.map +1 -1
- package/lib/bridge/buildTransaction.integration.test.js +17 -35
- package/lib/bridge/buildTransaction.integration.test.js.map +1 -1
- package/lib/bridge/buildTransaction.js +10 -21
- package/lib/bridge/buildTransaction.js.map +1 -1
- package/lib/bridge/buildTransaction.test.js +33 -130
- package/lib/bridge/buildTransaction.test.js.map +1 -1
- package/lib/bridge/getFeesForTransaction.d.ts.map +1 -1
- package/lib/bridge/getFeesForTransaction.js +5 -1
- package/lib/bridge/getFeesForTransaction.js.map +1 -1
- package/lib/logic/craftTransaction.d.ts +2 -2
- package/lib/logic/craftTransaction.d.ts.map +1 -1
- package/lib/logic/craftTransaction.integration.test.d.ts +2 -0
- package/lib/logic/craftTransaction.integration.test.d.ts.map +1 -0
- package/lib/logic/craftTransaction.integration.test.js +56 -0
- package/lib/logic/craftTransaction.integration.test.js.map +1 -0
- package/lib/logic/craftTransaction.js +2 -2
- package/lib/logic/craftTransaction.js.map +1 -1
- package/lib/logic/estimateFees.d.ts +1 -1
- package/lib/logic/estimateFees.d.ts.map +1 -1
- package/lib/logic/estimateFees.integration.test.d.ts +2 -0
- package/lib/logic/estimateFees.integration.test.d.ts.map +1 -0
- package/lib/logic/estimateFees.integration.test.js +79 -0
- package/lib/logic/estimateFees.integration.test.js.map +1 -0
- package/lib/logic/estimateFees.js +7 -2
- package/lib/logic/estimateFees.js.map +1 -1
- package/lib/logic/getBalance.d.ts.map +1 -1
- package/lib/logic/getBalance.integration.test.d.ts +2 -0
- package/lib/logic/getBalance.integration.test.d.ts.map +1 -0
- package/lib/logic/getBalance.integration.test.js +56 -0
- package/lib/logic/getBalance.integration.test.js.map +1 -0
- package/lib/logic/getBalance.js +18 -7
- package/lib/logic/getBalance.js.map +1 -1
- package/lib/logic/getBalance.test.js +49 -7
- package/lib/logic/getBalance.test.js.map +1 -1
- package/lib/logic/index.d.ts +1 -0
- package/lib/logic/index.d.ts.map +1 -1
- package/lib/logic/index.js +4 -1
- package/lib/logic/index.js.map +1 -1
- package/lib/logic/staking.d.ts +4 -0
- package/lib/logic/staking.d.ts.map +1 -0
- package/lib/logic/staking.js +36 -0
- package/lib/logic/staking.js.map +1 -0
- package/lib/network/index.d.ts +6 -6
- package/lib/network/index.d.ts.map +1 -1
- package/lib/network/index.js +9 -3
- package/lib/network/index.js.map +1 -1
- package/lib/network/sdk.d.ts +27 -19
- package/lib/network/sdk.d.ts.map +1 -1
- package/lib/network/sdk.integration.test.js +21 -22
- package/lib/network/sdk.integration.test.js.map +1 -1
- package/lib/network/sdk.js +113 -68
- package/lib/network/sdk.js.map +1 -1
- package/lib/network/sdk.test.js +148 -65
- package/lib/network/sdk.test.js.map +1 -1
- package/lib/test/testUtils.d.ts +2 -0
- package/lib/test/testUtils.d.ts.map +1 -0
- package/lib/test/testUtils.js +35 -0
- package/lib/test/testUtils.js.map +1 -0
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.integration.test.js +21 -2
- package/lib-es/api/index.integration.test.js.map +1 -1
- package/lib-es/api/index.js +3 -1
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/api/index.test.js +37 -0
- package/lib-es/api/index.test.js.map +1 -1
- package/lib-es/bridge/buildTransaction.d.ts +1 -3
- package/lib-es/bridge/buildTransaction.d.ts.map +1 -1
- package/lib-es/bridge/buildTransaction.integration.test.js +13 -31
- package/lib-es/bridge/buildTransaction.integration.test.js.map +1 -1
- package/lib-es/bridge/buildTransaction.js +9 -16
- package/lib-es/bridge/buildTransaction.js.map +1 -1
- package/lib-es/bridge/buildTransaction.test.js +34 -131
- package/lib-es/bridge/buildTransaction.test.js.map +1 -1
- package/lib-es/bridge/getFeesForTransaction.d.ts.map +1 -1
- package/lib-es/bridge/getFeesForTransaction.js +5 -1
- package/lib-es/bridge/getFeesForTransaction.js.map +1 -1
- package/lib-es/logic/craftTransaction.d.ts +2 -2
- package/lib-es/logic/craftTransaction.d.ts.map +1 -1
- package/lib-es/logic/craftTransaction.integration.test.d.ts +2 -0
- package/lib-es/logic/craftTransaction.integration.test.d.ts.map +1 -0
- package/lib-es/logic/craftTransaction.integration.test.js +51 -0
- package/lib-es/logic/craftTransaction.integration.test.js.map +1 -0
- package/lib-es/logic/craftTransaction.js +2 -2
- package/lib-es/logic/craftTransaction.js.map +1 -1
- package/lib-es/logic/estimateFees.d.ts +1 -1
- package/lib-es/logic/estimateFees.d.ts.map +1 -1
- package/lib-es/logic/estimateFees.integration.test.d.ts +2 -0
- package/lib-es/logic/estimateFees.integration.test.d.ts.map +1 -0
- package/lib-es/logic/estimateFees.integration.test.js +74 -0
- package/lib-es/logic/estimateFees.integration.test.js.map +1 -0
- package/lib-es/logic/estimateFees.js +7 -2
- package/lib-es/logic/estimateFees.js.map +1 -1
- package/lib-es/logic/getBalance.d.ts.map +1 -1
- package/lib-es/logic/getBalance.integration.test.d.ts +2 -0
- package/lib-es/logic/getBalance.integration.test.d.ts.map +1 -0
- package/lib-es/logic/getBalance.integration.test.js +51 -0
- package/lib-es/logic/getBalance.integration.test.js.map +1 -0
- package/lib-es/logic/getBalance.js +19 -8
- package/lib-es/logic/getBalance.js.map +1 -1
- package/lib-es/logic/getBalance.test.js +50 -8
- package/lib-es/logic/getBalance.test.js.map +1 -1
- package/lib-es/logic/index.d.ts +1 -0
- package/lib-es/logic/index.d.ts.map +1 -1
- package/lib-es/logic/index.js +1 -0
- package/lib-es/logic/index.js.map +1 -1
- package/lib-es/logic/staking.d.ts +4 -0
- package/lib-es/logic/staking.d.ts.map +1 -0
- package/lib-es/logic/staking.js +8 -0
- package/lib-es/logic/staking.js.map +1 -0
- package/lib-es/network/index.d.ts +6 -6
- package/lib-es/network/index.d.ts.map +1 -1
- package/lib-es/network/index.js +6 -3
- package/lib-es/network/index.js.map +1 -1
- package/lib-es/network/sdk.d.ts +27 -19
- package/lib-es/network/sdk.d.ts.map +1 -1
- package/lib-es/network/sdk.integration.test.js +22 -23
- package/lib-es/network/sdk.integration.test.js.map +1 -1
- package/lib-es/network/sdk.js +106 -64
- package/lib-es/network/sdk.js.map +1 -1
- package/lib-es/network/sdk.test.js +148 -65
- package/lib-es/network/sdk.test.js.map +1 -1
- package/lib-es/test/testUtils.d.ts +2 -0
- package/lib-es/test/testUtils.d.ts.map +1 -0
- package/lib-es/test/testUtils.js +31 -0
- package/lib-es/test/testUtils.js.map +1 -0
- package/package.json +7 -7
- package/src/api/index.integration.test.ts +24 -2
- package/src/api/index.test.ts +40 -0
- package/src/api/index.ts +4 -0
- package/src/bridge/buildTransaction.integration.test.ts +14 -39
- package/src/bridge/buildTransaction.test.ts +37 -160
- package/src/bridge/buildTransaction.ts +12 -21
- package/src/bridge/getFeesForTransaction.ts +6 -1
- package/src/logic/craftTransaction.integration.test.ts +63 -0
- package/src/logic/craftTransaction.ts +4 -4
- package/src/logic/estimateFees.integration.test.ts +89 -0
- package/src/logic/estimateFees.ts +7 -1
- package/src/logic/getBalance.integration.test.ts +66 -0
- package/src/logic/getBalance.test.ts +58 -8
- package/src/logic/getBalance.ts +24 -8
- package/src/logic/index.ts +1 -0
- package/src/logic/staking.ts +10 -0
- package/src/network/index.ts +12 -3
- package/src/network/sdk.integration.test.ts +25 -22
- package/src/network/sdk.test.ts +186 -77
- package/src/network/sdk.ts +149 -93
- package/src/test/testUtils.ts +38 -0
package/src/logic/getBalance.ts
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getStakes, getAllBalancesCached } from "../network";
|
|
2
2
|
import { Balance } from "@ledgerhq/coin-framework/api/types";
|
|
3
|
+
import { toSuiAsset } from "../network/sdk";
|
|
3
4
|
|
|
4
5
|
export async function getBalance(address: string): Promise<Balance[]> {
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
];
|
|
6
|
+
const [native, staking] = await Promise.all([
|
|
7
|
+
getNativeBalance(address),
|
|
8
|
+
getStakingBalances(address),
|
|
9
|
+
]);
|
|
10
|
+
return [...native, ...staking];
|
|
12
11
|
}
|
|
12
|
+
|
|
13
|
+
const getNativeBalance = async (address: string): Promise<Balance[]> => {
|
|
14
|
+
const balances = await getAllBalancesCached(address);
|
|
15
|
+
return balances.map(({ coinType, totalBalance }) => ({
|
|
16
|
+
value: BigInt(totalBalance),
|
|
17
|
+
asset: toSuiAsset(coinType),
|
|
18
|
+
}));
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const getStakingBalances = (address: string): Promise<Balance[]> =>
|
|
22
|
+
getStakes(address).then(stakes =>
|
|
23
|
+
stakes.map(stake => ({
|
|
24
|
+
value: stake.amount,
|
|
25
|
+
asset: stake.asset,
|
|
26
|
+
stake: stake,
|
|
27
|
+
})),
|
|
28
|
+
);
|
package/src/logic/index.ts
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Cursor, Page, Stake, Reward } from "@ledgerhq/coin-framework/api/types";
|
|
2
|
+
import * as sdk from "../network";
|
|
3
|
+
|
|
4
|
+
export const getStakes = (address: string, _cursor?: Cursor): Promise<Page<Stake>> => {
|
|
5
|
+
return sdk.getStakes(address).then(stakes => ({ items: stakes }));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const getRewards = (_address: string, _cursor?: Cursor): Promise<Page<Reward>> => {
|
|
9
|
+
throw new Error("getRewards is not supported");
|
|
10
|
+
};
|
package/src/network/index.ts
CHANGED
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
import {
|
|
2
|
-
getAccount,
|
|
3
2
|
getAccountBalances,
|
|
3
|
+
getAllBalancesCached,
|
|
4
4
|
getOperations,
|
|
5
|
+
getBlock,
|
|
6
|
+
getBlockInfo,
|
|
7
|
+
getStakes,
|
|
5
8
|
paymentInfo,
|
|
6
9
|
createTransaction,
|
|
7
10
|
executeTransactionBlock,
|
|
8
11
|
} from "./sdk";
|
|
9
12
|
|
|
10
13
|
export {
|
|
11
|
-
getAccount,
|
|
12
14
|
getAccountBalances,
|
|
15
|
+
getAllBalancesCached,
|
|
13
16
|
getOperations,
|
|
17
|
+
getBlock,
|
|
18
|
+
getBlockInfo,
|
|
19
|
+
getStakes,
|
|
14
20
|
paymentInfo,
|
|
15
21
|
createTransaction,
|
|
16
22
|
executeTransactionBlock,
|
|
17
23
|
};
|
|
18
24
|
|
|
19
25
|
export default {
|
|
20
|
-
getAccount,
|
|
21
26
|
getAccountBalances,
|
|
27
|
+
getAllBalancesCached,
|
|
22
28
|
getOperations,
|
|
29
|
+
getBlock,
|
|
30
|
+
getBlockInfo,
|
|
31
|
+
getStakes,
|
|
23
32
|
paymentInfo,
|
|
24
33
|
createTransaction,
|
|
25
34
|
executeTransactionBlock,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
paymentInfo,
|
|
11
11
|
getBlock,
|
|
12
12
|
getBlockInfo,
|
|
13
|
+
getStakes,
|
|
13
14
|
} from "./sdk";
|
|
14
15
|
import { getFullnodeUrl } from "@mysten/sui/client";
|
|
15
16
|
|
|
@@ -189,26 +190,6 @@ describe("SUI SDK Integration tests", () => {
|
|
|
189
190
|
expect(checkpointById.transactions.length).toEqual(19);
|
|
190
191
|
expect(checkpointById.digest).toEqual(checkpointBySequenceNumber.digest);
|
|
191
192
|
});
|
|
192
|
-
/*
|
|
193
|
-
test("getCheckpointWithTransactions", async () => {
|
|
194
|
-
const { checkpoint: checkpointById, transactions: checkpointByIdTransactions } =
|
|
195
|
-
await getCheckpointWithTransactions("3Q4zW4ieWnNgKLEq6kvVfP35PX2tBDUJERTWYyyz4eyS");
|
|
196
|
-
const {
|
|
197
|
-
checkpoint: checkpointBySequenceNumber,
|
|
198
|
-
transactions: checkpointBySequenceNumberTransactions,
|
|
199
|
-
} = await getCheckpointWithTransactions("164167623");
|
|
200
|
-
expect(checkpointById.epoch).toEqual("814");
|
|
201
|
-
expect(checkpointById.sequenceNumber).toEqual("164167623");
|
|
202
|
-
expect(checkpointById.timestampMs).toEqual("1751696298663");
|
|
203
|
-
expect(checkpointById.digest).toEqual("3Q4zW4ieWnNgKLEq6kvVfP35PX2tBDUJERTWYyyz4eyS");
|
|
204
|
-
expect(checkpointById.previousDigest).toEqual("6VKtVnpxstb968SzSrgYJ7zy5LXgFB6PnNHSJsT8Wr4E");
|
|
205
|
-
expect(checkpointById.transactions.length).toEqual(19);
|
|
206
|
-
expect(checkpointById).toEqual(checkpointBySequenceNumber);
|
|
207
|
-
expect(checkpointByIdTransactions.length).toEqual(19);
|
|
208
|
-
expect(checkpointBySequenceNumberTransactions.length).toEqual(19);
|
|
209
|
-
expect(checkpointByIdTransactions).toEqual(checkpointBySequenceNumberTransactions);
|
|
210
|
-
});
|
|
211
|
-
*/
|
|
212
193
|
});
|
|
213
194
|
|
|
214
195
|
describe("getBlockInfo", () => {
|
|
@@ -219,7 +200,7 @@ describe("SUI SDK Integration tests", () => {
|
|
|
219
200
|
expect(blockById.hash).toEqual("3Q4zW4ieWnNgKLEq6kvVfP35PX2tBDUJERTWYyyz4eyS");
|
|
220
201
|
expect(blockById.time).toEqual(new Date(1751696298663));
|
|
221
202
|
expect(blockById.parent?.height).toEqual(164167622);
|
|
222
|
-
|
|
203
|
+
expect(blockById.parent?.hash).toEqual("6VKtVnpxstb968SzSrgYJ7zy5LXgFB6PnNHSJsT8Wr4E");
|
|
223
204
|
expect(blockById).toEqual(blockBySequenceNumber);
|
|
224
205
|
});
|
|
225
206
|
});
|
|
@@ -232,9 +213,31 @@ describe("SUI SDK Integration tests", () => {
|
|
|
232
213
|
expect(blockById.info.hash).toEqual("3Q4zW4ieWnNgKLEq6kvVfP35PX2tBDUJERTWYyyz4eyS");
|
|
233
214
|
expect(blockById.info.time).toEqual(new Date(1751696298663));
|
|
234
215
|
expect(blockById.info.parent?.height).toEqual(164167622);
|
|
235
|
-
|
|
216
|
+
expect(blockById.info.parent?.hash).toEqual("6VKtVnpxstb968SzSrgYJ7zy5LXgFB6PnNHSJsT8Wr4E");
|
|
236
217
|
expect(blockById.transactions.length).toEqual(19);
|
|
237
218
|
expect(blockById).toEqual(blockBySequenceNumber);
|
|
238
219
|
});
|
|
239
220
|
});
|
|
221
|
+
|
|
222
|
+
describe("getStakes", () => {
|
|
223
|
+
test("Account 0xea438b6ce07762ea61e04af4d405dfcf197d5f77d30765f365f75460380f3cce", async () => {
|
|
224
|
+
const stakes = await getStakes(
|
|
225
|
+
"0xea438b6ce07762ea61e04af4d405dfcf197d5f77d30765f365f75460380f3cce",
|
|
226
|
+
);
|
|
227
|
+
expect(stakes.length).toBeGreaterThan(0);
|
|
228
|
+
stakes.forEach(stake => {
|
|
229
|
+
expect(stake.uid).toMatch(/0x[0-9a-z]+/);
|
|
230
|
+
expect(stake.address).toMatch(/0x[0-9a-z]+/);
|
|
231
|
+
expect(stake.delegate).toMatch(/0x[0-9a-z]+/);
|
|
232
|
+
expect(stake.state).toMatch(/(activating|active|inactive)/);
|
|
233
|
+
expect(stake.asset).toEqual({ type: "native" });
|
|
234
|
+
expect(stake.amount).toBeGreaterThan(0);
|
|
235
|
+
expect(stake.amountDeposited).toBeGreaterThan(0);
|
|
236
|
+
expect(stake.amountRewarded).toBeGreaterThanOrEqual(0);
|
|
237
|
+
// @ts-expect-error properties are defined
|
|
238
|
+
expect(stake.amount).toEqual(stake.amountDeposited + stake.amountRewarded);
|
|
239
|
+
expect(stake.details).toBeDefined();
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
});
|
|
240
243
|
});
|
package/src/network/sdk.test.ts
CHANGED
|
@@ -1,50 +1,3 @@
|
|
|
1
|
-
// Move all jest.mock calls to the very top
|
|
2
|
-
jest.mock("../config", () => ({
|
|
3
|
-
__esModule: true,
|
|
4
|
-
default: {
|
|
5
|
-
getCoinConfig: jest.fn(() => ({ node: { url: "http://test.com" } })),
|
|
6
|
-
setCoinConfig: jest.fn(),
|
|
7
|
-
},
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
jest.mock("../utils", () => ({
|
|
11
|
-
ensureAddressFormat: jest.fn((addr: string) => addr),
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
jest.mock("@ledgerhq/live-network/cache", () => ({
|
|
15
|
-
makeLRUCache: jest.fn(() => jest.fn()),
|
|
16
|
-
minutes: jest.fn(() => 60000),
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
jest.mock("@ledgerhq/logs", () => ({
|
|
20
|
-
log: jest.fn(),
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
jest.mock("@mysten/sui/client", () => {
|
|
24
|
-
const mockClient = {
|
|
25
|
-
queryTransactionBlocks: jest.fn(),
|
|
26
|
-
getBalance: jest.fn(),
|
|
27
|
-
getLatestCheckpointSequenceNumber: jest.fn(),
|
|
28
|
-
getCheckpoint: jest.fn(),
|
|
29
|
-
dryRunTransactionBlock: jest.fn(),
|
|
30
|
-
executeTransactionBlock: jest.fn(),
|
|
31
|
-
};
|
|
32
|
-
return {
|
|
33
|
-
SuiClient: jest.fn().mockImplementation(() => mockClient),
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
jest.mock("@mysten/sui/transactions", () => ({
|
|
38
|
-
Transaction: jest.fn().mockImplementation(() => ({
|
|
39
|
-
setSender: jest.fn().mockReturnThis(),
|
|
40
|
-
splitCoins: jest.fn().mockReturnValue([{ id: "coin1" }]),
|
|
41
|
-
transferObjects: jest.fn().mockReturnThis(),
|
|
42
|
-
gas: { id: "gas" },
|
|
43
|
-
build: jest.fn().mockResolvedValue(new Uint8Array([1, 2, 3])),
|
|
44
|
-
})),
|
|
45
|
-
}));
|
|
46
|
-
|
|
47
|
-
// Now import after mocks
|
|
48
1
|
import * as sdk from "./sdk";
|
|
49
2
|
import coinConfig from "../config";
|
|
50
3
|
|
|
@@ -215,6 +168,16 @@ const mockTransaction = {
|
|
|
215
168
|
|
|
216
169
|
const mockApi = new SuiClient({ url: "mock" }) as jest.Mocked<SuiClient>;
|
|
217
170
|
|
|
171
|
+
// Helper function to generate mock coins from an array of balances
|
|
172
|
+
const createMockCoins = (balances: string[]): any[] => {
|
|
173
|
+
return balances.map((balance, index) => ({
|
|
174
|
+
coinObjectId: `0xcoin${index + 1}`,
|
|
175
|
+
balance,
|
|
176
|
+
digest: `0xdigest${index + 1}`,
|
|
177
|
+
version: "1",
|
|
178
|
+
}));
|
|
179
|
+
};
|
|
180
|
+
|
|
218
181
|
beforeAll(() => {
|
|
219
182
|
coinConfig.setCoinConfig(() => ({
|
|
220
183
|
status: {
|
|
@@ -320,9 +283,9 @@ describe("SDK Functions", () => {
|
|
|
320
283
|
});
|
|
321
284
|
|
|
322
285
|
test("getOperationDate should return correct date", () => {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
);
|
|
286
|
+
const date = sdk.getOperationDate(mockTransaction as SuiTransactionBlockResponse);
|
|
287
|
+
expect(date).toBeDefined();
|
|
288
|
+
expect(date).toBeInstanceOf(Date);
|
|
326
289
|
});
|
|
327
290
|
|
|
328
291
|
test("getOperationCoinType should extract token coin type", () => {
|
|
@@ -534,33 +497,6 @@ describe("SDK Functions", () => {
|
|
|
534
497
|
expect(info).toHaveProperty("fees");
|
|
535
498
|
});
|
|
536
499
|
|
|
537
|
-
test("getCoinObjectIds should return array of object IDs for token transactions", async () => {
|
|
538
|
-
const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
|
|
539
|
-
const transaction = {
|
|
540
|
-
mode: "token.send" as const,
|
|
541
|
-
coinType: "0x123::test::TOKEN",
|
|
542
|
-
amount: new BigNumber(100),
|
|
543
|
-
recipient: "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164",
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
const coinObjectIds = await sdk.getCoinObjectIds(address, transaction);
|
|
547
|
-
expect(Array.isArray(coinObjectIds)).toBe(true);
|
|
548
|
-
expect(coinObjectIds).toContain("0xtest_coin_object_id");
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
test("getCoinObjectIds should return null for SUI transactions", async () => {
|
|
552
|
-
const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
|
|
553
|
-
const transaction = {
|
|
554
|
-
mode: "send" as const,
|
|
555
|
-
coinType: sdk.DEFAULT_COIN_TYPE,
|
|
556
|
-
amount: new BigNumber(100),
|
|
557
|
-
recipient: "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164",
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
const coinObjectIds = await sdk.getCoinObjectIds(address, transaction);
|
|
561
|
-
expect(coinObjectIds).toBeNull();
|
|
562
|
-
});
|
|
563
|
-
|
|
564
500
|
test("createTransaction should build a transaction", async () => {
|
|
565
501
|
const address = "0x6e143fe0a8ca010a86580dafac44298e5b1b7d73efc345356a59a15f0d7824f0";
|
|
566
502
|
const transaction = {
|
|
@@ -1531,3 +1467,176 @@ describe("filterOperations", () => {
|
|
|
1531
1467
|
});
|
|
1532
1468
|
});
|
|
1533
1469
|
});
|
|
1470
|
+
|
|
1471
|
+
describe("getCoinsForAmount", () => {
|
|
1472
|
+
const mockAddress = "0x33444cf803c690db96527cec67e3c9ab512596f4ba2d4eace43f0b4f716e0164";
|
|
1473
|
+
const mockCoinType = "0x2::sui::SUI";
|
|
1474
|
+
|
|
1475
|
+
beforeEach(() => {
|
|
1476
|
+
mockApi.getCoins.mockReset();
|
|
1477
|
+
});
|
|
1478
|
+
|
|
1479
|
+
describe("basic functionality", () => {
|
|
1480
|
+
test("handles single coin scenarios", async () => {
|
|
1481
|
+
const sufficientCoins = createMockCoins(["1000"]);
|
|
1482
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: sufficientCoins, hasNextPage: false });
|
|
1483
|
+
|
|
1484
|
+
let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1485
|
+
expect(result).toHaveLength(1);
|
|
1486
|
+
expect(result[0].balance).toBe("1000");
|
|
1487
|
+
|
|
1488
|
+
const insufficientCoins = createMockCoins(["500"]);
|
|
1489
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: insufficientCoins, hasNextPage: false });
|
|
1490
|
+
|
|
1491
|
+
result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1492
|
+
expect(result).toHaveLength(1);
|
|
1493
|
+
expect(result[0].balance).toBe("500");
|
|
1494
|
+
});
|
|
1495
|
+
|
|
1496
|
+
test("selects minimum coins needed", async () => {
|
|
1497
|
+
const exactMatchCoins = createMockCoins(["600", "400", "300"]);
|
|
1498
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: exactMatchCoins, hasNextPage: false });
|
|
1499
|
+
|
|
1500
|
+
let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1501
|
+
expect(result).toHaveLength(2);
|
|
1502
|
+
expect(result[0].balance).toBe("600");
|
|
1503
|
+
expect(result[1].balance).toBe("400");
|
|
1504
|
+
|
|
1505
|
+
const exceedCoins = createMockCoins(["800", "400", "200"]);
|
|
1506
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: exceedCoins, hasNextPage: false });
|
|
1507
|
+
|
|
1508
|
+
result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1509
|
+
expect(result).toHaveLength(2);
|
|
1510
|
+
expect(result[0].balance).toBe("800");
|
|
1511
|
+
expect(result[1].balance).toBe("400");
|
|
1512
|
+
});
|
|
1513
|
+
|
|
1514
|
+
test("handles edge cases", async () => {
|
|
1515
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: [], hasNextPage: false });
|
|
1516
|
+
|
|
1517
|
+
let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1518
|
+
expect(result).toHaveLength(0);
|
|
1519
|
+
|
|
1520
|
+
const coins = createMockCoins(["1000"]);
|
|
1521
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: coins, hasNextPage: false });
|
|
1522
|
+
|
|
1523
|
+
result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 0);
|
|
1524
|
+
expect(result).toHaveLength(0);
|
|
1525
|
+
});
|
|
1526
|
+
});
|
|
1527
|
+
|
|
1528
|
+
describe("sorting and filtering", () => {
|
|
1529
|
+
test("filters zero balance coins", async () => {
|
|
1530
|
+
const mockCoins = createMockCoins(["1000", "500"]);
|
|
1531
|
+
mockCoins.splice(1, 0, createMockCoins(["0"])[0]);
|
|
1532
|
+
mockCoins.push({ coinObjectId: "0xcoin4", balance: "0", digest: "0xdigest4", version: "1" });
|
|
1533
|
+
|
|
1534
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: mockCoins, hasNextPage: false });
|
|
1535
|
+
|
|
1536
|
+
const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1537
|
+
|
|
1538
|
+
expect(result).toHaveLength(1);
|
|
1539
|
+
expect(result[0].balance).toBe("1000");
|
|
1540
|
+
expect(result.every(coin => parseInt(coin.balance) > 0)).toBe(true);
|
|
1541
|
+
});
|
|
1542
|
+
|
|
1543
|
+
test("sorts and optimizes coin selection", async () => {
|
|
1544
|
+
const unsortedCoins = createMockCoins(["100", "800", "300", "500"]);
|
|
1545
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: unsortedCoins, hasNextPage: false });
|
|
1546
|
+
|
|
1547
|
+
let result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1548
|
+
expect(result).toHaveLength(2);
|
|
1549
|
+
expect(result[0].balance).toBe("800");
|
|
1550
|
+
expect(result[1].balance).toBe("500");
|
|
1551
|
+
|
|
1552
|
+
const mixedCoins = createMockCoins(["200", "800", "400"]);
|
|
1553
|
+
mixedCoins.unshift(createMockCoins(["0"])[0]);
|
|
1554
|
+
mixedCoins.splice(2, 0, createMockCoins(["0"])[0]);
|
|
1555
|
+
|
|
1556
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: mixedCoins, hasNextPage: false });
|
|
1557
|
+
|
|
1558
|
+
result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1559
|
+
expect(result).toHaveLength(2);
|
|
1560
|
+
expect(result[0].balance).toBe("800");
|
|
1561
|
+
expect(result[1].balance).toBe("400");
|
|
1562
|
+
expect(result.every(coin => parseInt(coin.balance) > 0)).toBe(true);
|
|
1563
|
+
});
|
|
1564
|
+
|
|
1565
|
+
test("handles all zero balance coins", async () => {
|
|
1566
|
+
const mockCoins = createMockCoins(["0", "0", "0"]);
|
|
1567
|
+
mockApi.getCoins.mockResolvedValueOnce({ data: mockCoins, hasNextPage: false });
|
|
1568
|
+
|
|
1569
|
+
const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1570
|
+
|
|
1571
|
+
expect(result).toHaveLength(0);
|
|
1572
|
+
expect(result).toEqual([]);
|
|
1573
|
+
});
|
|
1574
|
+
});
|
|
1575
|
+
|
|
1576
|
+
describe("pagination", () => {
|
|
1577
|
+
test("handles single page scenarios", async () => {
|
|
1578
|
+
const mockCoins = createMockCoins(["800", "400", "300"]);
|
|
1579
|
+
mockApi.getCoins.mockResolvedValueOnce({
|
|
1580
|
+
data: mockCoins,
|
|
1581
|
+
hasNextPage: true,
|
|
1582
|
+
nextCursor: "cursor1",
|
|
1583
|
+
});
|
|
1584
|
+
|
|
1585
|
+
const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1586
|
+
|
|
1587
|
+
expect(result).toHaveLength(2);
|
|
1588
|
+
expect(result[0].balance).toBe("800");
|
|
1589
|
+
expect(result[1].balance).toBe("400");
|
|
1590
|
+
expect(mockApi.getCoins).toHaveBeenCalledTimes(1);
|
|
1591
|
+
});
|
|
1592
|
+
|
|
1593
|
+
test("handles multi-page scenarios", async () => {
|
|
1594
|
+
const firstPageCoins = createMockCoins(["300", "200"]);
|
|
1595
|
+
const secondPageCoins = createMockCoins(["600", "400", "100"]);
|
|
1596
|
+
|
|
1597
|
+
mockApi.getCoins
|
|
1598
|
+
.mockResolvedValueOnce({
|
|
1599
|
+
data: firstPageCoins,
|
|
1600
|
+
hasNextPage: true,
|
|
1601
|
+
nextCursor: "cursor1",
|
|
1602
|
+
})
|
|
1603
|
+
.mockResolvedValueOnce({
|
|
1604
|
+
data: secondPageCoins,
|
|
1605
|
+
hasNextPage: false,
|
|
1606
|
+
});
|
|
1607
|
+
|
|
1608
|
+
const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1609
|
+
|
|
1610
|
+
expect(result).toHaveLength(3);
|
|
1611
|
+
expect(result[0].balance).toBe("300");
|
|
1612
|
+
expect(result[1].balance).toBe("200");
|
|
1613
|
+
expect(result[2].balance).toBe("600");
|
|
1614
|
+
expect(mockApi.getCoins).toHaveBeenCalledTimes(2);
|
|
1615
|
+
});
|
|
1616
|
+
|
|
1617
|
+
test("handles insufficient funds across pages", async () => {
|
|
1618
|
+
const firstPageCoins = createMockCoins(["300", "200"]);
|
|
1619
|
+
const secondPageCoins = createMockCoins(["200", "100"]);
|
|
1620
|
+
|
|
1621
|
+
mockApi.getCoins
|
|
1622
|
+
.mockResolvedValueOnce({
|
|
1623
|
+
data: firstPageCoins,
|
|
1624
|
+
hasNextPage: true,
|
|
1625
|
+
nextCursor: "cursor1",
|
|
1626
|
+
})
|
|
1627
|
+
.mockResolvedValueOnce({
|
|
1628
|
+
data: secondPageCoins,
|
|
1629
|
+
hasNextPage: false,
|
|
1630
|
+
});
|
|
1631
|
+
|
|
1632
|
+
const result = await sdk.getCoinsForAmount(mockApi, mockAddress, mockCoinType, 1000);
|
|
1633
|
+
|
|
1634
|
+
expect(result).toHaveLength(4);
|
|
1635
|
+
expect(result[0].balance).toBe("300");
|
|
1636
|
+
expect(result[1].balance).toBe("200");
|
|
1637
|
+
expect(result[2].balance).toBe("200");
|
|
1638
|
+
expect(result[3].balance).toBe("100");
|
|
1639
|
+
expect(mockApi.getCoins).toHaveBeenCalledTimes(2);
|
|
1640
|
+
});
|
|
1641
|
+
});
|
|
1642
|
+
});
|