@thru/thru-sdk 0.1.19 → 0.1.21

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.
Files changed (88) hide show
  1. package/README.md +19 -0
  2. package/dist/{chunk-PH7P5EEU.js → chunk-SHMREHP5.js} +13 -9
  3. package/dist/chunk-SHMREHP5.js.map +1 -0
  4. package/dist/client.d.ts +2 -1
  5. package/dist/client.js +3 -2
  6. package/dist/client.js.map +1 -1
  7. package/dist/metafile-esm.json +1 -1
  8. package/dist/sdk.d.ts +3 -3
  9. package/dist/sdk.js +1 -1
  10. package/dist/{transactions-BzD9hYlc.d.ts → transactions-CLezIeXO.d.ts} +20 -18
  11. package/package.json +7 -3
  12. package/buf.gen.yaml +0 -12
  13. package/buf.lock +0 -9
  14. package/buf.yaml +0 -15
  15. package/dist/chunk-PH7P5EEU.js.map +0 -1
  16. package/proto/thru/common/v1/consensus.proto +0 -73
  17. package/proto/thru/common/v1/errors.proto +0 -65
  18. package/proto/thru/common/v1/filters.proto +0 -60
  19. package/proto/thru/common/v1/pagination.proto +0 -45
  20. package/proto/thru/core/v1/account.proto +0 -137
  21. package/proto/thru/core/v1/block.proto +0 -80
  22. package/proto/thru/core/v1/state.proto +0 -35
  23. package/proto/thru/core/v1/transaction.proto +0 -136
  24. package/proto/thru/core/v1/types.proto +0 -50
  25. package/proto/thru/services/v1/command_service.proto +0 -70
  26. package/proto/thru/services/v1/query_service.proto +0 -344
  27. package/proto/thru/services/v1/streaming_service.proto +0 -126
  28. package/thru-ts-client-sdk/__tests__/helpers/test-utils.ts +0 -228
  29. package/thru-ts-client-sdk/client.ts +0 -10
  30. package/thru-ts-client-sdk/core/__tests__/bound-client.test.ts +0 -354
  31. package/thru-ts-client-sdk/core/__tests__/client.test.ts +0 -53
  32. package/thru-ts-client-sdk/core/bound-client.ts +0 -156
  33. package/thru-ts-client-sdk/core/client.ts +0 -38
  34. package/thru-ts-client-sdk/defaults.ts +0 -26
  35. package/thru-ts-client-sdk/modules/__tests__/accounts.test.ts +0 -406
  36. package/thru-ts-client-sdk/modules/__tests__/blocks.test.ts +0 -199
  37. package/thru-ts-client-sdk/modules/__tests__/events.test.ts +0 -74
  38. package/thru-ts-client-sdk/modules/__tests__/height.test.ts +0 -39
  39. package/thru-ts-client-sdk/modules/__tests__/helpers.test.ts +0 -288
  40. package/thru-ts-client-sdk/modules/__tests__/keys.test.ts +0 -55
  41. package/thru-ts-client-sdk/modules/__tests__/proofs.test.ts +0 -119
  42. package/thru-ts-client-sdk/modules/__tests__/streaming.test.ts +0 -152
  43. package/thru-ts-client-sdk/modules/__tests__/transactions.test.ts +0 -730
  44. package/thru-ts-client-sdk/modules/__tests__/version.test.ts +0 -40
  45. package/thru-ts-client-sdk/modules/accounts.ts +0 -141
  46. package/thru-ts-client-sdk/modules/blocks.ts +0 -75
  47. package/thru-ts-client-sdk/modules/events.ts +0 -20
  48. package/thru-ts-client-sdk/modules/height.ts +0 -9
  49. package/thru-ts-client-sdk/modules/helpers.ts +0 -131
  50. package/thru-ts-client-sdk/modules/keys.ts +0 -29
  51. package/thru-ts-client-sdk/modules/proofs.ts +0 -20
  52. package/thru-ts-client-sdk/modules/streaming.ts +0 -133
  53. package/thru-ts-client-sdk/modules/transactions.ts +0 -374
  54. package/thru-ts-client-sdk/modules/version.ts +0 -10
  55. package/thru-ts-client-sdk/proto/buf/validate/validate_pb.ts +0 -4761
  56. package/thru-ts-client-sdk/proto/google/api/annotations_pb.ts +0 -39
  57. package/thru-ts-client-sdk/proto/google/api/client_pb.ts +0 -953
  58. package/thru-ts-client-sdk/proto/google/api/field_behavior_pb.ts +0 -157
  59. package/thru-ts-client-sdk/proto/google/api/http_pb.ts +0 -474
  60. package/thru-ts-client-sdk/proto/google/api/launch_stage_pb.ts +0 -118
  61. package/thru-ts-client-sdk/proto/thru/common/v1/consensus_pb.ts +0 -162
  62. package/thru-ts-client-sdk/proto/thru/common/v1/errors_pb.ts +0 -129
  63. package/thru-ts-client-sdk/proto/thru/common/v1/filters_pb.ts +0 -129
  64. package/thru-ts-client-sdk/proto/thru/common/v1/pagination_pb.ts +0 -79
  65. package/thru-ts-client-sdk/proto/thru/core/v1/account_pb.ts +0 -359
  66. package/thru-ts-client-sdk/proto/thru/core/v1/block_pb.ts +0 -259
  67. package/thru-ts-client-sdk/proto/thru/core/v1/state_pb.ts +0 -103
  68. package/thru-ts-client-sdk/proto/thru/core/v1/transaction_pb.ts +0 -528
  69. package/thru-ts-client-sdk/proto/thru/core/v1/types_pb.ts +0 -100
  70. package/thru-ts-client-sdk/proto/thru/services/v1/command_service_pb.ts +0 -146
  71. package/thru-ts-client-sdk/proto/thru/services/v1/query_service_pb.ts +0 -819
  72. package/thru-ts-client-sdk/proto/thru/services/v1/streaming_service_pb.ts +0 -390
  73. package/thru-ts-client-sdk/sdk.ts +0 -42
  74. package/thru-ts-client-sdk/test-scripts/counter.ts +0 -469
  75. package/thru-ts-client-sdk/test-scripts/create-account.ts +0 -74
  76. package/thru-ts-client-sdk/test-scripts/get-height.ts +0 -52
  77. package/thru-ts-client-sdk/transactions/Transaction.ts +0 -240
  78. package/thru-ts-client-sdk/transactions/TransactionBuilder.ts +0 -53
  79. package/thru-ts-client-sdk/transactions/__tests__/TransactionBuilder.test.ts +0 -411
  80. package/thru-ts-client-sdk/transactions/__tests__/utils.test.ts +0 -214
  81. package/thru-ts-client-sdk/transactions/index.ts +0 -3
  82. package/thru-ts-client-sdk/transactions/types.ts +0 -74
  83. package/thru-ts-client-sdk/transactions/utils.ts +0 -132
  84. package/thru-ts-client-sdk/types/types.ts +0 -8
  85. package/thru-ts-client-sdk/utils/utils.ts +0 -27
  86. package/tsconfig.json +0 -9
  87. package/tsup.config.ts +0 -14
  88. package/vitest.config.ts +0 -31
@@ -1,199 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { createMockBlock, createMockContext, createMockListBlocksResponse } from "../../__tests__/helpers/test-utils";
3
- import { ConsensusStatus } from "../../proto/thru/common/v1/consensus_pb";
4
- import { BlockView } from "../../proto/thru/core/v1/block_pb";
5
- import { getBlock, getRawBlock, listBlocks } from "../blocks";
6
-
7
- describe("blocks", () => {
8
- describe("getBlock", () => {
9
- it("should get block by slot (number)", async () => {
10
- const ctx = createMockContext();
11
- const mockBlock = createMockBlock({ header: { slot: 1000n } });
12
- vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
13
-
14
- const result = await getBlock(ctx, { slot: 1000 });
15
-
16
- expect(result).toBe(mockBlock);
17
- expect(ctx.query.getBlock).toHaveBeenCalledTimes(1);
18
- const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
19
- expect(callArgs.selector.case).toBe("slot");
20
- expect(callArgs.selector.value).toBe(1000n);
21
- });
22
-
23
- it("should get block by slot (bigint)", async () => {
24
- const ctx = createMockContext();
25
- const mockBlock = createMockBlock({ header: { slot: 1000n } });
26
- vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
27
-
28
- const result = await getBlock(ctx, { slot: 1000n });
29
-
30
- expect(result).toBe(mockBlock);
31
- const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
32
- expect(callArgs.selector.case).toBe("slot");
33
- expect(callArgs.selector.value).toBe(1000n);
34
- });
35
-
36
- it("should get block by blockHash", async () => {
37
- const ctx = createMockContext();
38
- const mockBlock = createMockBlock();
39
- const blockHash = new Uint8Array(32);
40
- blockHash.fill(0x42);
41
- vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
42
-
43
- const result = await getBlock(ctx, { blockHash });
44
-
45
- expect(result).toBe(mockBlock);
46
- const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
47
- expect(callArgs.selector.case).toBe("blockHash");
48
- expect(callArgs.selector.value.value).toEqual(blockHash);
49
- });
50
-
51
- it("should use default view when not provided", async () => {
52
- const ctx = createMockContext();
53
- const mockBlock = createMockBlock();
54
- vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
55
-
56
- await getBlock(ctx, { slot: 1000 });
57
-
58
- const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
59
- expect(callArgs.view).toBe(BlockView.FULL);
60
- });
61
-
62
- it("should use custom view when provided", async () => {
63
- const ctx = createMockContext();
64
- const mockBlock = createMockBlock();
65
- vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
66
-
67
- await getBlock(ctx, { slot: 1000 }, { view: BlockView.HEADER_ONLY });
68
-
69
- const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
70
- expect(callArgs.view).toBe(BlockView.HEADER_ONLY);
71
- });
72
-
73
- it("should use default minConsensus when not provided", async () => {
74
- const ctx = createMockContext();
75
- const mockBlock = createMockBlock();
76
- vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
77
-
78
- await getBlock(ctx, { slot: 1000 });
79
-
80
- const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
81
- expect(callArgs.minConsensus).toBe(ConsensusStatus.UNSPECIFIED);
82
- });
83
-
84
- it("should use custom minConsensus when provided", async () => {
85
- const ctx = createMockContext();
86
- const mockBlock = createMockBlock();
87
- vi.spyOn(ctx.query, "getBlock").mockResolvedValue(mockBlock);
88
-
89
- await getBlock(ctx, { slot: 1000 }, { minConsensus: ConsensusStatus.FINALIZED });
90
-
91
- const callArgs = (ctx.query.getBlock as any).mock.calls[0][0];
92
- expect(callArgs.minConsensus).toBe(ConsensusStatus.FINALIZED);
93
- });
94
- });
95
-
96
- describe("getRawBlock", () => {
97
- it("should get raw block by slot", async () => {
98
- const ctx = createMockContext();
99
- const mockRawBlock = { slot: 1000n, rawBlock: new Uint8Array([1, 2, 3]) };
100
- vi.spyOn(ctx.query, "getRawBlock").mockResolvedValue(mockRawBlock as any);
101
-
102
- const result = await getRawBlock(ctx, { slot: 1000 });
103
-
104
- expect(result).toBe(mockRawBlock);
105
- expect(ctx.query.getRawBlock).toHaveBeenCalledTimes(1);
106
- });
107
-
108
- it("should get raw block by blockHash", async () => {
109
- const ctx = createMockContext();
110
- const blockHash = new Uint8Array(32);
111
- blockHash.fill(0x42);
112
- const mockRawBlock = { slot: 1000n, rawBlock: new Uint8Array([1, 2, 3]) };
113
- vi.spyOn(ctx.query, "getRawBlock").mockResolvedValue(mockRawBlock as any);
114
-
115
- const result = await getRawBlock(ctx, { blockHash });
116
-
117
- expect(result).toBe(mockRawBlock);
118
- const callArgs = (ctx.query.getRawBlock as any).mock.calls[0][0];
119
- expect(callArgs.selector.case).toBe("blockHash");
120
- });
121
-
122
- it("should use default minConsensus", async () => {
123
- const ctx = createMockContext();
124
- const mockRawBlock = { slot: 1000n, rawBlock: new Uint8Array() };
125
- vi.spyOn(ctx.query, "getRawBlock").mockResolvedValue(mockRawBlock as any);
126
-
127
- await getRawBlock(ctx, { slot: 1000 });
128
-
129
- const callArgs = (ctx.query.getRawBlock as any).mock.calls[0][0];
130
- expect(callArgs.minConsensus).toBe(ConsensusStatus.UNSPECIFIED);
131
- });
132
- });
133
-
134
- describe("listBlocks", () => {
135
- it("should list blocks with default options", async () => {
136
- const ctx = createMockContext();
137
- const mockResponse = createMockListBlocksResponse();
138
- vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
139
-
140
- const result = await listBlocks(ctx);
141
-
142
- expect(result).toBe(mockResponse);
143
- expect(ctx.query.listBlocks).toHaveBeenCalledTimes(1);
144
- const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
145
- expect(callArgs.view).toBe(BlockView.FULL);
146
- expect(callArgs.minConsensus).toBe(ConsensusStatus.UNSPECIFIED);
147
- });
148
-
149
- it("should list blocks with custom view", async () => {
150
- const ctx = createMockContext();
151
- const mockResponse = createMockListBlocksResponse();
152
- vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
153
-
154
- await listBlocks(ctx, { view: BlockView.HEADER_ONLY });
155
-
156
- const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
157
- expect(callArgs.view).toBe(BlockView.HEADER_ONLY);
158
- });
159
-
160
- it("should list blocks with filter", async () => {
161
- const ctx = createMockContext();
162
- const mockResponse = createMockListBlocksResponse();
163
- const filter = { expression: "slot > 1000" };
164
- vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
165
-
166
- await listBlocks(ctx, { filter: filter as any });
167
-
168
- const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
169
- expect(callArgs.filter).toBeDefined();
170
- expect(callArgs.filter.expression).toBe("slot > 1000");
171
- });
172
-
173
- it("should list blocks with pagination", async () => {
174
- const ctx = createMockContext();
175
- const mockResponse = createMockListBlocksResponse();
176
- const page = { pageSize: 10, pageToken: "token" };
177
- vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
178
-
179
- await listBlocks(ctx, { page: page as any });
180
-
181
- const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
182
- expect(callArgs.page).toBeDefined();
183
- expect(callArgs.page.pageSize).toBe(10);
184
- expect(callArgs.page.pageToken).toBe("token");
185
- });
186
-
187
- it("should list blocks with custom minConsensus", async () => {
188
- const ctx = createMockContext();
189
- const mockResponse = createMockListBlocksResponse();
190
- vi.spyOn(ctx.query, "listBlocks").mockResolvedValue(mockResponse);
191
-
192
- await listBlocks(ctx, { minConsensus: ConsensusStatus.FINALIZED });
193
-
194
- const callArgs = (ctx.query.listBlocks as any).mock.calls[0][0];
195
- expect(callArgs.minConsensus).toBe(ConsensusStatus.FINALIZED);
196
- });
197
- });
198
- });
199
-
@@ -1,74 +0,0 @@
1
- import { create } from "@bufbuild/protobuf";
2
- import { describe, expect, it, vi } from "vitest";
3
- import { createMockContext } from "../../__tests__/helpers/test-utils";
4
- import { CurrentVersionSchema, VersionContextSchema } from "../../proto/thru/common/v1/consensus_pb";
5
- import { EventSchema } from "../../proto/thru/services/v1/query_service_pb";
6
- import { getEvent } from "../events";
7
-
8
- describe("events", () => {
9
- describe("getEvent", () => {
10
- it("should return event with valid eventId", async () => {
11
- const ctx = createMockContext();
12
- const mockEvent = create(EventSchema, {
13
- eventId: "test-event-id",
14
- slot: 1000n,
15
- });
16
-
17
- vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
18
-
19
- const result = await getEvent(ctx, "test-event-id");
20
-
21
- expect(result).toBe(mockEvent);
22
- expect(result.eventId).toBe("test-event-id");
23
- expect(ctx.query.getEvent).toHaveBeenCalledTimes(1);
24
- });
25
-
26
- it("should include eventId in request", async () => {
27
- const ctx = createMockContext();
28
- const mockEvent = create(EventSchema, { eventId: "test-event-id" });
29
- vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
30
-
31
- await getEvent(ctx, "test-event-id");
32
-
33
- const callArgs = (ctx.query.getEvent as any).mock.calls[0][0];
34
- expect(callArgs.eventId).toBe("test-event-id");
35
- });
36
-
37
- it("should include version context when provided", async () => {
38
- const ctx = createMockContext();
39
- const mockEvent = create(EventSchema, { eventId: "test-event-id" });
40
- vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
41
-
42
- const versionContext = create(VersionContextSchema, {
43
- version: {
44
- case: "current",
45
- value: create(CurrentVersionSchema, {}),
46
- },
47
- });
48
-
49
- await getEvent(ctx, "test-event-id", { versionContext });
50
-
51
- const callArgs = (ctx.query.getEvent as any).mock.calls[0][0];
52
- expect(callArgs.versionContext).toBeDefined();
53
- expect(callArgs.versionContext.version?.case).toBe("current");
54
- });
55
-
56
- it("should throw error for empty eventId", () => {
57
- const ctx = createMockContext();
58
-
59
- expect(() => getEvent(ctx, "")).toThrow("eventId is required");
60
- });
61
-
62
- it("should not include version context when not provided", async () => {
63
- const ctx = createMockContext();
64
- const mockEvent = create(EventSchema, { eventId: "test-event-id" });
65
- vi.spyOn(ctx.query, "getEvent").mockResolvedValue(mockEvent);
66
-
67
- await getEvent(ctx, "test-event-id");
68
-
69
- const callArgs = (ctx.query.getEvent as any).mock.calls[0][0];
70
- expect(callArgs.versionContext).toBeUndefined();
71
- });
72
- });
73
- });
74
-
@@ -1,39 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { createMockContext, createMockHeightResponse } from "../../__tests__/helpers/test-utils";
3
- import { getBlockHeight } from "../height";
4
-
5
- describe("height", () => {
6
- describe("getBlockHeight", () => {
7
- it("should return height response", async () => {
8
- const ctx = createMockContext();
9
- const mockResponse = createMockHeightResponse({
10
- finalized: 1000n,
11
- locallyExecuted: 1001n,
12
- clusterExecuted: 1002n,
13
- });
14
-
15
- vi.spyOn(ctx.query, "getHeight").mockResolvedValue(mockResponse);
16
-
17
- const result = await getBlockHeight(ctx);
18
-
19
- expect(result).toBe(mockResponse);
20
- expect(result.finalized).toBe(1000n);
21
- expect(result.locallyExecuted).toBe(1001n);
22
- expect(result.clusterExecuted).toBe(1002n);
23
- expect(ctx.query.getHeight).toHaveBeenCalledTimes(1);
24
- });
25
-
26
- it("should create empty request", async () => {
27
- const ctx = createMockContext();
28
- const mockResponse = createMockHeightResponse();
29
- vi.spyOn(ctx.query, "getHeight").mockResolvedValue(mockResponse);
30
-
31
- await getBlockHeight(ctx);
32
-
33
- const callArgs = (ctx.query.getHeight as any).mock.calls[0][0];
34
- // Request should be created (empty GetHeightRequest)
35
- expect(callArgs).toBeDefined();
36
- });
37
- });
38
- });
39
-
@@ -1,288 +0,0 @@
1
- import { decodeAddress, decodeSignature } from "@thru/helpers";
2
- import { describe, expect, it } from "vitest";
3
- import { generateTestAddress, generateTestPubkey, generateTestSignature, generateTestSignatureString } from "../../__tests__/helpers/test-utils";
4
- import {
5
- deriveProgramAddress,
6
- toBlockHash,
7
- toPubkey,
8
- toSignature,
9
- } from "../helpers";
10
-
11
- describe("helpers", () => {
12
- describe("toSignature", () => {
13
- it("should accept Uint8Array with 64 bytes", () => {
14
- const sigBytes = generateTestSignature();
15
- const result = toSignature(sigBytes);
16
-
17
- expect(result.value).toEqual(sigBytes);
18
- expect(result.value.length).toBe(64);
19
- });
20
-
21
- it("should accept ts- prefixed signature string", () => {
22
- const sigString = generateTestSignatureString();
23
- const result = toSignature(sigString);
24
-
25
- expect(result.value.length).toBe(64);
26
- // Verify it decodes correctly
27
- const decoded = decodeSignature(sigString);
28
- expect(result.value).toEqual(decoded);
29
- });
30
-
31
- it("should accept base64 signature string", () => {
32
- const sigBytes = generateTestSignature();
33
- const base64 = btoa(String.fromCharCode(...sigBytes));
34
- const result = toSignature(base64);
35
-
36
- expect(result.value.length).toBe(64);
37
- expect(result.value).toEqual(sigBytes);
38
- });
39
-
40
- it("should throw error for Uint8Array with wrong length", () => {
41
- const invalidSig = new Uint8Array(32); // Should be 64
42
-
43
- expect(() => toSignature(invalidSig)).toThrow("signature must contain 64 bytes");
44
- });
45
-
46
- it("should throw error for invalid input type", () => {
47
- expect(() => toSignature(null as any)).toThrow("signature is required");
48
- expect(() => toSignature(undefined as any)).toThrow("signature is required");
49
- });
50
- });
51
-
52
- describe("toPubkey", () => {
53
- it("should accept Uint8Array with 32 bytes", () => {
54
- const pubkeyBytes = generateTestPubkey();
55
- const result = toPubkey(pubkeyBytes, "testField");
56
-
57
- expect(result.value).toEqual(pubkeyBytes);
58
- expect(result.value.length).toBe(32);
59
- });
60
-
61
- it("should accept ta- prefixed address string", () => {
62
- const address = generateTestAddress();
63
- const result = toPubkey(address, "testField");
64
-
65
- expect(result.value.length).toBe(32);
66
- // Verify it decodes correctly
67
- const decoded = decodeAddress(address);
68
- expect(result.value).toEqual(decoded);
69
- });
70
-
71
- it("should accept base64 pubkey string", () => {
72
- const pubkeyBytes = generateTestPubkey();
73
- const base64 = btoa(String.fromCharCode(...pubkeyBytes));
74
- const result = toPubkey(base64, "testField");
75
-
76
- expect(result.value.length).toBe(32);
77
- expect(result.value).toEqual(pubkeyBytes);
78
- });
79
-
80
- it("should throw error for Uint8Array with wrong length", () => {
81
- const invalidPubkey = new Uint8Array(64); // Should be 32
82
-
83
- expect(() => toPubkey(invalidPubkey, "testField")).toThrow("testField must contain 32 bytes");
84
- });
85
-
86
- it("should throw error for invalid input type", () => {
87
- expect(() => toPubkey(null as any, "testField")).toThrow("testField is required");
88
- expect(() => toPubkey(undefined as any, "testField")).toThrow("testField is required");
89
- });
90
-
91
- it("should include field name in error message", () => {
92
- const invalidPubkey = new Uint8Array(64);
93
-
94
- expect(() => toPubkey(invalidPubkey, "myCustomField")).toThrow("myCustomField must contain 32 bytes");
95
- });
96
- });
97
-
98
- describe("toBlockHash", () => {
99
- it("should accept Uint8Array", () => {
100
- const hashBytes = new Uint8Array([1, 2, 3, 4]);
101
- const result = toBlockHash(hashBytes);
102
-
103
- expect(result.value).toEqual(hashBytes);
104
- });
105
-
106
- it("should accept base64 string", () => {
107
- const hashBytes = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
108
- const base64 = btoa(String.fromCharCode(...hashBytes));
109
- const result = toBlockHash(base64);
110
-
111
- expect(result.value).toBeInstanceOf(Uint8Array);
112
- expect(result.value).toEqual(hashBytes);
113
- });
114
-
115
- it("should accept hex string", () => {
116
- const hashBytes = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
117
- const hexString = Array.from(hashBytes)
118
- .map(b => b.toString(16).padStart(2, "0"))
119
- .join("");
120
- const result = toBlockHash(hexString);
121
-
122
- expect(result.value).toBeInstanceOf(Uint8Array);
123
- // Note: ensureBytes may handle hex differently, so we just verify it works
124
- expect(result.value.length).toBeGreaterThan(0);
125
- });
126
- });
127
-
128
- describe("deriveProgramAddress", () => {
129
- it("should derive address from program address and seed (Uint8Array)", () => {
130
- const programAddress = generateTestPubkey(0x01);
131
- const seed = new Uint8Array([0x02, 0x03]);
132
-
133
- const result = deriveProgramAddress({
134
- programAddress,
135
- seed,
136
- });
137
-
138
- expect(result.bytes).toBeInstanceOf(Uint8Array);
139
- expect(result.bytes.length).toBe(32);
140
- expect(result.address).toBeTruthy();
141
- expect(result.address.startsWith("ta")).toBe(true);
142
- });
143
-
144
- it("should derive address with ephemeral flag set", () => {
145
- const programAddress = generateTestPubkey(0x01);
146
- const seed = new Uint8Array([0x02, 0x03]);
147
-
148
- const resultEphemeral = deriveProgramAddress({
149
- programAddress,
150
- seed,
151
- ephemeral: true,
152
- });
153
-
154
- const resultNonEphemeral = deriveProgramAddress({
155
- programAddress,
156
- seed,
157
- ephemeral: false,
158
- });
159
-
160
- // Ephemeral and non-ephemeral should produce different addresses
161
- expect(resultEphemeral.bytes).not.toEqual(resultNonEphemeral.bytes);
162
- expect(resultEphemeral.address).not.toBe(resultNonEphemeral.address);
163
- });
164
-
165
- it("should be deterministic for same inputs", () => {
166
- const programAddress = generateTestPubkey(0x01);
167
- const seed = new Uint8Array([0x02, 0x03]);
168
-
169
- const result1 = deriveProgramAddress({
170
- programAddress,
171
- seed,
172
- });
173
-
174
- const result2 = deriveProgramAddress({
175
- programAddress,
176
- seed,
177
- });
178
-
179
- expect(result1.bytes).toEqual(result2.bytes);
180
- expect(result1.address).toBe(result2.address);
181
- });
182
-
183
- it("should accept program address as ta- prefixed string", () => {
184
- const programAddress = generateTestAddress(0x01);
185
- const seed = new Uint8Array([0x02, 0x03]);
186
-
187
- const result = deriveProgramAddress({
188
- programAddress,
189
- seed,
190
- });
191
-
192
- expect(result.bytes.length).toBe(32);
193
- expect(result.address).toBeTruthy();
194
- });
195
-
196
- it("should accept program address as hex string", () => {
197
- const programAddressBytes = generateTestPubkey(0x01);
198
- const programAddressHex = Array.from(programAddressBytes)
199
- .map(b => b.toString(16).padStart(2, "0"))
200
- .join("");
201
-
202
- const seed = new Uint8Array([0x02, 0x03]);
203
-
204
- const result = deriveProgramAddress({
205
- programAddress: programAddressHex,
206
- seed,
207
- });
208
-
209
- expect(result.bytes.length).toBe(32);
210
- expect(result.address).toBeTruthy();
211
- });
212
-
213
- it("should accept seed as string", () => {
214
- const programAddress = generateTestPubkey(0x01);
215
- const seed = "my-seed-string";
216
-
217
- const result = deriveProgramAddress({
218
- programAddress,
219
- seed,
220
- });
221
-
222
- expect(result.bytes.length).toBe(32);
223
- expect(result.address).toBeTruthy();
224
- });
225
-
226
- it("should accept seed as hex string", () => {
227
- const programAddress = generateTestPubkey(0x01);
228
- const seedBytes = new Uint8Array(32);
229
- seedBytes.fill(0x42);
230
- const seedHex = Array.from(seedBytes)
231
- .map(b => b.toString(16).padStart(2, "0"))
232
- .join("");
233
-
234
- const result = deriveProgramAddress({
235
- programAddress,
236
- seed: seedHex,
237
- });
238
-
239
- expect(result.bytes.length).toBe(32);
240
- expect(result.address).toBeTruthy();
241
- });
242
-
243
- it("should throw error for invalid program address length", () => {
244
- const invalidProgramAddress = new Uint8Array(31); // Should be 32
245
- const seed = new Uint8Array([0x02]);
246
-
247
- expect(() => deriveProgramAddress({
248
- programAddress: invalidProgramAddress,
249
- seed,
250
- })).toThrow("Program address must contain 32 bytes");
251
- });
252
-
253
- it("should throw error for empty seed", () => {
254
- const programAddress = generateTestPubkey(0x01);
255
-
256
- expect(() => deriveProgramAddress({
257
- programAddress,
258
- seed: "",
259
- })).toThrow("Seed cannot be empty");
260
-
261
- expect(() => deriveProgramAddress({
262
- programAddress,
263
- seed: new Uint8Array(0),
264
- })).toThrow("Seed cannot be empty");
265
- });
266
-
267
- it("should throw error for seed too long", () => {
268
- const programAddress = generateTestPubkey(0x01);
269
- const longSeed = new Uint8Array(33); // Max is 32
270
-
271
- expect(() => deriveProgramAddress({
272
- programAddress,
273
- seed: longSeed,
274
- })).toThrow("Seed cannot exceed 32 bytes");
275
- });
276
-
277
- it("should throw error for invalid program address format", () => {
278
- const invalidProgramAddress = "invalid-format";
279
- const seed = new Uint8Array([0x02]);
280
-
281
- expect(() => deriveProgramAddress({
282
- programAddress: invalidProgramAddress,
283
- seed,
284
- })).toThrow("Program address must be a 32-byte value, ta-address, or 64-character hex string");
285
- });
286
- });
287
- });
288
-
@@ -1,55 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { generateKeyPair } from "../keys";
3
-
4
- describe("keys", () => {
5
- describe("generateKeyPair", () => {
6
- it("should generate valid keypair", async () => {
7
- const result = await generateKeyPair();
8
-
9
- expect(result).toBeDefined();
10
- expect(result.address).toBeTruthy();
11
- expect(result.publicKey).toBeInstanceOf(Uint8Array);
12
- expect(result.privateKey).toBeInstanceOf(Uint8Array);
13
- });
14
-
15
- it("should generate 32-byte public key", async () => {
16
- const result = await generateKeyPair();
17
-
18
- expect(result.publicKey.length).toBe(32);
19
- });
20
-
21
- it("should generate 32-byte private key (Ed25519 seed)", async () => {
22
- const result = await generateKeyPair();
23
-
24
- expect(result.privateKey.length).toBe(32);
25
- });
26
-
27
- it("should generate address starting with 'ta'", async () => {
28
- const result = await generateKeyPair();
29
-
30
- expect(result.address.startsWith("ta")).toBe(true);
31
- });
32
-
33
- it("should generate different keypairs on each call", async () => {
34
- const result1 = await generateKeyPair();
35
- const result2 = await generateKeyPair();
36
-
37
- // All fields should be different (very unlikely to be same)
38
- expect(result1.address).not.toBe(result2.address);
39
- expect(result1.publicKey).not.toEqual(result2.publicKey);
40
- expect(result1.privateKey).not.toEqual(result2.privateKey);
41
- });
42
-
43
- it("should generate valid Ed25519 keypair format", async () => {
44
- const result = await generateKeyPair();
45
-
46
- // Public key should be 32 bytes
47
- expect(result.publicKey.length).toBe(32);
48
- // Private key should be 32 bytes (Ed25519 seed)
49
- expect(result.privateKey.length).toBe(32);
50
- // Address should be valid format
51
- expect(result.address.length).toBeGreaterThan(0);
52
- });
53
- });
54
- });
55
-