emblem-vault-sdk 2.3.6 → 3.0.0-experimental

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 (147) hide show
  1. package/.traces/blockchain-provider-abstraction-plan.md +302 -0
  2. package/.traces/notes.md +43 -0
  3. package/.traces/readme-verification-trace.md +988 -0
  4. package/.traces/test-migration-status.md +227 -0
  5. package/.traces/tests-consolidated-trace.md +667 -0
  6. package/dist/abi/abi.json +53 -0
  7. package/dist/bundle.js +21602 -17419
  8. package/dist/clients/emblemVaultSolanaWalletClient.d.ts +74 -0
  9. package/dist/clients/emblemVaultSolanaWalletClient.js +149 -0
  10. package/dist/clients/emblemVaultSolanaWalletClient.js.map +1 -0
  11. package/dist/clients/emblemVaultWalletClient.d.ts +52 -0
  12. package/dist/clients/emblemVaultWalletClient.js +110 -0
  13. package/dist/clients/emblemVaultWalletClient.js.map +1 -0
  14. package/dist/derive.js +7 -0
  15. package/dist/derive.js.map +1 -0
  16. package/dist/index.js +319 -114
  17. package/dist/index.js.map +1 -0
  18. package/dist/providers/ProviderManager.d.ts +57 -0
  19. package/dist/providers/ProviderManager.js +283 -0
  20. package/dist/providers/ProviderManager.js.map +1 -0
  21. package/dist/providers.d.ts +101 -0
  22. package/dist/providers.js +96 -0
  23. package/dist/providers.js.map +1 -0
  24. package/dist/types.js +1 -0
  25. package/dist/types.js.map +1 -0
  26. package/dist/utils.js +61 -58
  27. package/dist/utils.js.map +1 -0
  28. package/docs/bundle.js +21602 -17419
  29. package/docs/index.html +150 -13
  30. package/docs/local.html +385 -0
  31. package/docs/steps.html +420 -53
  32. package/package.json +22 -13
  33. package/readme.md +795 -21
  34. package/src/abi/abi.json +54 -1
  35. package/src/clients/emblemVaultSolanaWalletClient.ts +257 -0
  36. package/src/clients/emblemVaultWalletClient.ts +159 -0
  37. package/src/derive.ts +5 -5
  38. package/src/index.ts +320 -102
  39. package/src/providers/ProviderManager.ts +254 -0
  40. package/src/providers.ts +163 -0
  41. package/src/types.ts +50 -0
  42. package/src/utils.ts +63 -62
  43. package/test/.mocharc.js +8 -0
  44. package/test/README.md +212 -0
  45. package/test/fixtures/ethscriptions/balance-with-native-first.json +24 -0
  46. package/test/fixtures/ethscriptions/balance-with-native.json +23 -0
  47. package/test/fixtures/ethscriptions/balance.json +18 -0
  48. package/test/helpers/sdkLoader.js +88 -0
  49. package/test/helpers/setup.js +55 -0
  50. package/test/integration/ApiOperations.spec.js +102 -0
  51. package/test/integration/VaultAI.spec.js +57 -0
  52. package/test/integration/VaultCreation.spec.js +95 -0
  53. package/test/mocks.js +127 -0
  54. package/test/tsconfig.json +25 -0
  55. package/test/unit/AllowedBells.spec.js +53 -0
  56. package/test/unit/AllowedBitcoinDeGods.spec.js +53 -0
  57. package/test/unit/AllowedBitcoinOrdinals.spec.js +46 -0
  58. package/test/unit/AllowedCounterparty.spec.js +66 -0
  59. package/test/unit/AllowedCursedOrdinals.spec.js +68 -0
  60. package/test/unit/AllowedEmbells.spec.js +11 -0
  61. package/test/unit/AllowedEmbels.spec.js +11 -0
  62. package/test/unit/AllowedEmblemOpen.spec.js +20 -0
  63. package/test/unit/AllowedEthscriptions.spec.js +53 -0
  64. package/test/unit/AllowedHardcodedNfts.spec.js +77 -0
  65. package/test/unit/AllowedNamecoin.spec.js +33 -0
  66. package/test/unit/AllowedOrdi.spec.js +46 -0
  67. package/test/unit/AllowedOxbt.spec.js +46 -0
  68. package/test/unit/AllowedProjectCollection.spec.js +51 -0
  69. package/test/unit/AllowedProtocolCollection.spec.js +44 -0
  70. package/test/unit/AllowedStamps.spec.js +78 -0
  71. package/test/unit/DarkfarmsMetadata.spec.js +10 -0
  72. package/test/unit/EmblemVaultSdk.spec.js +188 -0
  73. package/test/unit/Providers.spec.js +290 -0
  74. package/test/unit/ResourceMonitor.spec.js +111 -0
  75. package/test/unit/SDKMemoryLeaks.spec.js +176 -0
  76. package/test/unit/Signing.spec.js +321 -0
  77. package/test/unit/VaultAI.spec.js +140 -0
  78. package/test/unit/clients/EmblemVaultSolanaWalletClient.spec.js +296 -0
  79. package/test/unit/clients/EmblemVaultWalletClient.spec.js +246 -0
  80. package/test/utils/ResourceMonitor.js +169 -0
  81. package/test/windsurf-rules.md +68 -0
  82. package/tsconfig.json +7 -3
  83. package/types/derive.d.ts +0 -5
  84. package/types/index.d.ts +152 -32
  85. package/types/types.d.ts +43 -0
  86. package/types/utils.d.ts +7 -1
  87. package/dist/abi/quote.js +0 -29
  88. package/dist/abi/quote.json +0 -26
  89. package/jest.config.js +0 -6
  90. package/tests/AllowedBells.test.ts +0 -53
  91. package/tests/AllowedBitcoinDeGods.test.ts +0 -53
  92. package/tests/AllowedBitcoinOrdinals.test.ts +0 -46
  93. package/tests/AllowedCounterparty.test.ts +0 -45
  94. package/tests/AllowedCursedOrdinals.test.ts +0 -68
  95. package/tests/AllowedEmbells.test.ts +0 -12
  96. package/tests/AllowedEmbels.test.ts +0 -16
  97. package/tests/AllowedEmblemOpen.test.ts +0 -20
  98. package/tests/AllowedEthscriptions.test.ts +0 -39
  99. package/tests/AllowedHardcodedNfts.test.ts +0 -78
  100. package/tests/AllowedNamecoin.test.ts +0 -33
  101. package/tests/AllowedOrdi.test.ts +0 -47
  102. package/tests/AllowedOxbt.test.ts +0 -47
  103. package/tests/AllowedProjectlCollection.test.ts +0 -51
  104. package/tests/AllowedProtocolCollection.test.ts +0 -44
  105. package/tests/AllowedStamps.test.ts +0 -73
  106. package/tests/DarkfarmsMetadata.test.ts +0 -10
  107. package/tests/EmblemVaultSdk.test.ts +0 -124
  108. package/tests/fixtures/embels/balance.json +0 -10
  109. package/tests/fixtures/ethscriptions/balance-with-native-first.json +0 -69
  110. package/tests/fixtures/ethscriptions/balance-with-native.json +0 -37
  111. package/tests/fixtures/ethscriptions/balance.json +0 -64
  112. /package/{tests → test}/fixtures/bells/balance-with-non-bell-first.json +0 -0
  113. /package/{tests → test}/fixtures/bells/balance-with-non-bell.json +0 -0
  114. /package/{tests → test}/fixtures/bells/balance.json +0 -0
  115. /package/{tests → test}/fixtures/bitcoin-degods/balance-with-non-degods-first.json +0 -0
  116. /package/{tests → test}/fixtures/bitcoin-degods/balance-with-non-degods.json +0 -0
  117. /package/{tests → test}/fixtures/bitcoin-degods/balance.json +0 -0
  118. /package/{tests → test}/fixtures/bitcoin-ordinals/balance-with-native-first.json +0 -0
  119. /package/{tests → test}/fixtures/bitcoin-ordinals/balance-with-only-native.json +0 -0
  120. /package/{tests → test}/fixtures/bitcoin-ordinals/balance.json +0 -0
  121. /package/{tests → test}/fixtures/counterparty/balance-with-multiple.json +0 -0
  122. /package/{tests → test}/fixtures/counterparty/balance.json +0 -0
  123. /package/{tests → test}/fixtures/cursed-ordinals/balance-with-native-first.json +0 -0
  124. /package/{tests → test}/fixtures/cursed-ordinals/balance-with-native.json +0 -0
  125. /package/{tests → test}/fixtures/cursed-ordinals/balance.json +0 -0
  126. /package/{tests → test}/fixtures/dogeparty/balance-with-non-dogeparty-first.json +0 -0
  127. /package/{tests → test}/fixtures/dogeparty/balance-with-non-dogeparty.json +0 -0
  128. /package/{tests → test}/fixtures/dogeparty/balance.json +0 -0
  129. /package/{tests → test}/fixtures/emblem-open/balance.json +0 -0
  130. /package/{tests → test}/fixtures/hardcoded-nfts/balance-witn-non-hardcoded-first.json +0 -0
  131. /package/{tests → test}/fixtures/hardcoded-nfts/balance-witn-non-hardcoded.json +0 -0
  132. /package/{tests → test}/fixtures/hardcoded-nfts/balance.json +0 -0
  133. /package/{tests → test}/fixtures/megapunks/balance-with-non-megapunk-first.json +0 -0
  134. /package/{tests → test}/fixtures/megapunks/balance-with-non-megapunk.json +0 -0
  135. /package/{tests → test}/fixtures/megapunks/balance.json +0 -0
  136. /package/{tests → test}/fixtures/namecoin/balance-with-native-first.json +0 -0
  137. /package/{tests → test}/fixtures/namecoin/balance-with-native.json +0 -0
  138. /package/{tests → test}/fixtures/namecoin/balance.json +0 -0
  139. /package/{tests → test}/fixtures/ordi/balance-with-native-first.json +0 -0
  140. /package/{tests → test}/fixtures/ordi/balance-with-native.json +0 -0
  141. /package/{tests → test}/fixtures/ordi/balance.json +0 -0
  142. /package/{tests → test}/fixtures/oxbt/balance-with-native-first.json +0 -0
  143. /package/{tests → test}/fixtures/oxbt/balance-with-native.json +0 -0
  144. /package/{tests → test}/fixtures/oxbt/balance.json +0 -0
  145. /package/{tests → test}/fixtures/stamps/balance-with-non-stamps-first.json +0 -0
  146. /package/{tests → test}/fixtures/stamps/balance-with-non-stamps.json +0 -0
  147. /package/{tests → test}/fixtures/stamps/balance.json +0 -0
@@ -0,0 +1,296 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
3
+ const { EmblemVaultSDK } = require('../../../dist/index.js');
4
+ const { expect } = require('chai');
5
+ const sinon = require('sinon');
6
+ const { createEmblemVaultSolanaWalletClient } = require('../../../dist/clients/emblemVaultSolanaWalletClient.js');
7
+ const {
8
+ Transaction,
9
+ VersionedTransaction,
10
+ PublicKey,
11
+ Connection,
12
+ Keypair,
13
+ SystemProgram,
14
+ LAMPORTS_PER_SOL,
15
+ MessageV0
16
+ } = require('@solana/web3.js');
17
+
18
+ // Mock SDK
19
+ const mockApiKey = 'mock-api-key';
20
+ class MockEmblemVaultSDK extends EmblemVaultSDK {
21
+ constructor(apiKey) {
22
+ super(apiKey);
23
+ // Override methods if necessary for testing setup
24
+ }
25
+ // Mock any methods needed by the client creation or its methods, if they are called internally
26
+ }
27
+
28
+ describe('EmblemVaultSolanaWalletClient', () => {
29
+ let sdk;
30
+ let walletClient;
31
+ let mockConnection;
32
+ const testWalletId = 'test-solana-wallet-001';
33
+
34
+ beforeEach(() => {
35
+ sdk = new MockEmblemVaultSDK(mockApiKey);
36
+ mockConnection = new Connection('http://localhost:8899', 'confirmed');
37
+ walletClient = createEmblemVaultSolanaWalletClient({
38
+ sdk: sdk,
39
+ walletId: testWalletId,
40
+ connection: mockConnection
41
+ });
42
+ });
43
+
44
+ afterEach(() => {
45
+ // Restore sinon spies/stubs after each test
46
+ sinon.restore();
47
+ });
48
+
49
+ it('should create a client instance', () => {
50
+ expect(walletClient).to.exist;
51
+ expect(walletClient.type).to.equal('emblemVaultSolanaWalletClient');
52
+ expect(walletClient.walletId).to.equal(testWalletId);
53
+ expect(walletClient.sdk).to.equal(sdk);
54
+ expect(walletClient.connection).to.equal(mockConnection);
55
+ });
56
+
57
+ it('should have the expected methods', () => {
58
+ expect(walletClient.getPublicKey).to.be.a('function');
59
+ expect(walletClient.signMessage).to.be.a('function');
60
+ expect(walletClient.signTransaction).to.be.a('function');
61
+ expect(walletClient.signVersionedTransaction).to.be.a('function');
62
+ expect(walletClient.sendTransaction).to.be.a('function');
63
+ expect(walletClient.sendVersionedTransaction).to.be.a('function');
64
+ });
65
+
66
+ describe('getPublicKey', () => {
67
+ it('should return a PublicKey instance', async () => {
68
+ const publicKey = await walletClient.getPublicKey();
69
+ expect(publicKey).to.be.instanceOf(PublicKey);
70
+ });
71
+
72
+ it('should cache the public key after first retrieval', async () => {
73
+ // First call should set the cached public key
74
+ const publicKey1 = await walletClient.getPublicKey();
75
+ expect(walletClient.publicKey).to.equal(publicKey1);
76
+
77
+ // Spy on the getPublicKey method
78
+ const getPublicKeySpy = sinon.spy(walletClient, 'getPublicKey');
79
+
80
+ // Second call should return the same public key
81
+ const publicKey2 = await walletClient.getPublicKey();
82
+ expect(publicKey2).to.deep.equal(publicKey1);
83
+
84
+ // Verify the method was called
85
+ expect(getPublicKeySpy.calledOnce).to.be.true;
86
+ });
87
+
88
+ it('should use provided public key if available', async () => {
89
+ const providedPublicKey = new PublicKey('11111111111111111111111111111111');
90
+ const clientWithPublicKey = createEmblemVaultSolanaWalletClient({
91
+ sdk: sdk,
92
+ walletId: testWalletId,
93
+ publicKey: providedPublicKey
94
+ });
95
+
96
+ const publicKey = await clientWithPublicKey.getPublicKey();
97
+ expect(publicKey).to.deep.equal(providedPublicKey);
98
+ });
99
+ });
100
+
101
+ describe('signMessage', () => {
102
+ it('should sign a string message', async () => {
103
+ const message = 'Hello, Solana!';
104
+ const signature = await walletClient.signMessage(message);
105
+
106
+ expect(signature).to.be.a('string');
107
+ // Base64 encoded signature
108
+ expect(signature).to.match(/^[A-Za-z0-9+/=]+$/);
109
+ });
110
+
111
+ it('should sign a Uint8Array message', async () => {
112
+ const message = new TextEncoder().encode('Hello, Solana!');
113
+ const signature = await walletClient.signMessage(message);
114
+
115
+ expect(signature).to.be.a('string');
116
+ // Base64 encoded signature
117
+ expect(signature).to.match(/^[A-Za-z0-9+/=]+$/);
118
+ });
119
+
120
+ it('should produce different signatures for different messages', async () => {
121
+ const message1 = 'Hello, Solana!';
122
+ const message2 = 'Different message';
123
+
124
+ const signature1 = await walletClient.signMessage(message1);
125
+ const signature2 = await walletClient.signMessage(message2);
126
+
127
+ // They should be different
128
+ expect(signature1).to.not.equal(signature2);
129
+ });
130
+ });
131
+
132
+ describe('signTransaction', () => {
133
+ it('should sign a transaction', async () => {
134
+ // Get the public key first
135
+ const publicKey = await walletClient.getPublicKey();
136
+
137
+ // Create a simple transaction
138
+ const transaction = new Transaction().add(
139
+ SystemProgram.transfer({
140
+ fromPubkey: publicKey,
141
+ toPubkey: new PublicKey('11111111111111111111111111111111'),
142
+ lamports: LAMPORTS_PER_SOL * 0.01
143
+ })
144
+ );
145
+
146
+ // Set recent blockhash
147
+ transaction.recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k';
148
+ transaction.feePayer = publicKey;
149
+
150
+ // Sign the transaction
151
+ const signedTx = await walletClient.signTransaction(transaction);
152
+
153
+ // Verify the transaction has signatures
154
+ expect(signedTx.signatures.length).to.be.greaterThan(0);
155
+ expect(signedTx.signatures[0].publicKey.toBase58()).to.equal(publicKey.toBase58());
156
+ });
157
+
158
+ it('should get the public key if not already cached', async () => {
159
+ // Create a client without a public key
160
+ const newClient = createEmblemVaultSolanaWalletClient({
161
+ sdk: sdk,
162
+ walletId: testWalletId,
163
+ connection: mockConnection
164
+ });
165
+
166
+ // Spy on the getPublicKey method
167
+ const getPublicKeySpy = sinon.spy(newClient, 'getPublicKey');
168
+
169
+ // Create a simple transaction
170
+ const transaction = new Transaction();
171
+
172
+ // Sign the transaction - this should call getPublicKey internally
173
+ await newClient.signTransaction(transaction);
174
+
175
+ // Verify getPublicKey was called
176
+ expect(getPublicKeySpy.calledOnce).to.be.true;
177
+ });
178
+ });
179
+
180
+ describe('signVersionedTransaction', () => {
181
+ it('should sign a versioned transaction', async () => {
182
+ // Get the public key first
183
+ const publicKey = await walletClient.getPublicKey();
184
+
185
+ // Create a mock versioned transaction
186
+ const mockVersionedTransaction = {
187
+ message: {
188
+ serialize: () => Buffer.from('mock-serialized-message')
189
+ }
190
+ };
191
+
192
+ // Sign the transaction
193
+ const signedTx = await walletClient.signVersionedTransaction(mockVersionedTransaction);
194
+
195
+ // In our mock implementation, we're just returning the original transaction
196
+ expect(signedTx).to.equal(mockVersionedTransaction);
197
+ });
198
+ });
199
+
200
+ describe('sendTransaction', () => {
201
+ it('should throw if no connection is provided', async () => {
202
+ // Create a client without a connection
203
+ const clientWithoutConnection = createEmblemVaultSolanaWalletClient({
204
+ sdk: sdk,
205
+ walletId: testWalletId
206
+ });
207
+
208
+ // Create a simple transaction
209
+ const transaction = new Transaction();
210
+
211
+ // Attempt to send the transaction
212
+ try {
213
+ await clientWithoutConnection.sendTransaction(transaction);
214
+ // If it doesn't throw, fail the test
215
+ expect.fail('sendTransaction should have thrown without a connection');
216
+ } catch (error) {
217
+ expect(error).to.be.instanceOf(Error);
218
+ expect(error.message).to.equal('Connection is required to send transactions');
219
+ }
220
+ });
221
+
222
+ it('should sign and send a transaction', async () => {
223
+ // Get the public key first
224
+ const publicKey = await walletClient.getPublicKey();
225
+
226
+ // Create a simple transaction
227
+ const transaction = new Transaction().add(
228
+ SystemProgram.transfer({
229
+ fromPubkey: publicKey,
230
+ toPubkey: new PublicKey('11111111111111111111111111111111'),
231
+ lamports: LAMPORTS_PER_SOL * 0.01
232
+ })
233
+ );
234
+
235
+ // Set recent blockhash
236
+ transaction.recentBlockhash = 'EETubP5AKHgjPAhzPAFcb8BAY1hMH639CWCFTqi3hq1k';
237
+ transaction.feePayer = publicKey;
238
+
239
+ // Send the transaction
240
+ const signature = await walletClient.sendTransaction(transaction);
241
+
242
+ // Verify a signature was returned
243
+ expect(signature).to.be.a('string');
244
+ expect(signature).to.include('mock_tx_signature');
245
+ });
246
+ });
247
+
248
+ describe('sendVersionedTransaction', () => {
249
+ it('should throw if no connection is provided', async () => {
250
+ // Create a client without a connection
251
+ const clientWithoutConnection = createEmblemVaultSolanaWalletClient({
252
+ sdk: sdk,
253
+ walletId: testWalletId
254
+ });
255
+
256
+ // Get the public key first
257
+ const publicKey = await clientWithoutConnection.getPublicKey();
258
+
259
+ // Create a mock versioned transaction
260
+ const mockVersionedTransaction = {
261
+ message: {
262
+ serialize: () => Buffer.from('mock-serialized-message')
263
+ }
264
+ };
265
+
266
+ // Attempt to send the transaction
267
+ try {
268
+ await clientWithoutConnection.sendVersionedTransaction(mockVersionedTransaction);
269
+ // If it doesn't throw, fail the test
270
+ expect.fail('sendVersionedTransaction should have thrown without a connection');
271
+ } catch (error) {
272
+ expect(error).to.be.instanceOf(Error);
273
+ expect(error.message).to.equal('Connection is required to send transactions');
274
+ }
275
+ });
276
+
277
+ it('should sign and send a versioned transaction', async () => {
278
+ // Get the public key first
279
+ const publicKey = await walletClient.getPublicKey();
280
+
281
+ // Create a mock versioned transaction
282
+ const mockVersionedTransaction = {
283
+ message: {
284
+ serialize: () => Buffer.from('mock-serialized-message')
285
+ }
286
+ };
287
+
288
+ // Send the transaction
289
+ const signature = await walletClient.sendVersionedTransaction(mockVersionedTransaction);
290
+
291
+ // Verify a signature was returned
292
+ expect(signature).to.be.a('string');
293
+ expect(signature).to.include('mock_tx_signature');
294
+ });
295
+ });
296
+ });
@@ -0,0 +1,246 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
3
+ const { EmblemVaultSDK } = require('../../../dist/index.js');
4
+ const { expect } = require('chai');
5
+ const sinon = require('sinon');
6
+ const { createEmblemVaultWalletClient } = require('../../../dist/clients/emblemVaultWalletClient.js');
7
+ const { parseEther } = require('viem');
8
+
9
+ // Mock SDK
10
+ const mockApiKey = 'mock-api-key';
11
+ class MockEmblemVaultSDK extends EmblemVaultSDK {
12
+ constructor(apiKey) {
13
+ super(apiKey);
14
+ // Override methods if necessary for testing setup
15
+ }
16
+ // Mock any methods needed by the client creation or its methods, if they are called internally
17
+ }
18
+
19
+ describe('EmblemVaultWalletClient', () => {
20
+ let sdk;
21
+ let walletClient;
22
+ const testWalletId = 'test-wallet-001';
23
+ const mockAccountAddress = '0xMockAddressFor' + testWalletId; // Consistent mock address
24
+
25
+ beforeEach(() => {
26
+ sdk = new MockEmblemVaultSDK(mockApiKey);
27
+ walletClient = createEmblemVaultWalletClient({
28
+ sdk: sdk,
29
+ walletId: testWalletId,
30
+ // Optionally provide a mock account here if needed for default tests
31
+ // account: { address: mockAccountAddress, type: 'json-rpc'} // type is required by viem Account
32
+ });
33
+ });
34
+
35
+ afterEach(() => {
36
+ // Restore sinon spies/stubs after each test
37
+ sinon.restore();
38
+ });
39
+
40
+ it('should create a client instance', () => {
41
+ expect(walletClient).to.exist;
42
+ expect(walletClient.type).to.equal('emblemVaultWalletClient');
43
+ expect(walletClient.walletId).to.equal(testWalletId);
44
+ expect(walletClient.sdk).to.equal(sdk);
45
+ });
46
+
47
+ it('should have the expected methods', () => {
48
+ expect(walletClient.getAddresses).to.be.a('function');
49
+ expect(walletClient.signMessage).to.be.a('function');
50
+ expect(walletClient.signTypedData).to.be.a('function');
51
+ expect(walletClient.sendTransaction).to.be.a('function');
52
+ });
53
+
54
+ describe('getAddresses', () => {
55
+ it('should return the mock address derived from walletId when no account is configured', async () => {
56
+ const addresses = await walletClient.getAddresses();
57
+ expect(addresses).to.be.an('array').with.lengthOf(1);
58
+ expect(addresses[0]).to.equal(mockAccountAddress);
59
+ });
60
+
61
+ it('should return the configured account address if provided', async () => {
62
+ const configuredAddress = '0xConfiguredAccountAddress001';
63
+ const clientWithAccount = createEmblemVaultWalletClient({
64
+ sdk: sdk,
65
+ walletId: testWalletId,
66
+ account: { address: configuredAddress, type: 'local',
67
+ publicKey: '0x', // Added mock publicKey
68
+ source: 'custom', // Added mock source
69
+ signMessage: async () => '0x',
70
+ signTransaction: async () => '0x',
71
+ signTypedData: async () => '0x' }
72
+ });
73
+ const addresses = await clientWithAccount.getAddresses();
74
+ expect(addresses).to.be.an('array').with.lengthOf(1);
75
+ expect(addresses[0]).to.equal(configuredAddress);
76
+ });
77
+
78
+ it('should return the configured account address from Account object', async () => {
79
+ const configuredAddress = '0xConfiguredAccountObjectAddress002';
80
+ const clientWithAccount = createEmblemVaultWalletClient({
81
+ sdk: sdk,
82
+ walletId: testWalletId,
83
+ account: { address: configuredAddress, type: 'local',
84
+ publicKey: '0x', // Added mock publicKey
85
+ source: 'custom', // Added mock source
86
+ signMessage: async () => '0x',
87
+ signTransaction: async () => '0x',
88
+ signTypedData: async () => '0x' }
89
+ });
90
+ const addresses = await clientWithAccount.getAddresses();
91
+ expect(addresses).to.be.an('array').with.lengthOf(1);
92
+ expect(addresses[0]).to.equal(configuredAddress);
93
+ });
94
+ });
95
+
96
+ describe('signMessage', () => {
97
+ it('should return a mock signature string', async () => {
98
+ const message = 'Hello, Emblem!';
99
+ const signature = await walletClient.signMessage({ message, account: mockAccountAddress });
100
+
101
+ expect(signature).to.be.a('string');
102
+ expect(signature).to.match(/^0x[a-f0-9]+$/); // Check for hex format
103
+ expect(signature).to.include(Buffer.from(`mock_signature_for_${testWalletId}`).toString('hex'));
104
+ });
105
+
106
+ it('should use the account provided in parameters', async () => {
107
+ const specificAccount = '0xSpecificAccountForMsg003';
108
+ // Spy on the signMessage method directly
109
+ const signMessageSpy = sinon.spy(walletClient, 'signMessage');
110
+ await walletClient.signMessage({ message: 'Hello, specific account!', account: specificAccount });
111
+ // Verify the method was called with the specific account
112
+ expect(signMessageSpy.calledWith(sinon.match({
113
+ message: 'Hello, specific account!',
114
+ account: specificAccount
115
+ }))).to.be.true;
116
+ });
117
+ });
118
+
119
+ describe('signTypedData', () => {
120
+ // EIP712 Domain definition
121
+ const domain = {
122
+ name: 'Ether Mail',
123
+ version: '1',
124
+ chainId: 1,
125
+ verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
126
+ };
127
+
128
+ // The named type definitions
129
+ const types = {
130
+ Person: [
131
+ { name: 'name', type: 'string' },
132
+ { name: 'wallet', type: 'address' },
133
+ ],
134
+ Mail: [
135
+ { name: 'from', type: 'Person' },
136
+ { name: 'to', type: 'Person' },
137
+ { name: 'contents', type: 'string' },
138
+ ],
139
+ };
140
+
141
+ // The data to sign
142
+ const message = {
143
+ from: {
144
+ name: 'Alice',
145
+ wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
146
+ },
147
+ to: {
148
+ name: 'Bob',
149
+ wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
150
+ },
151
+ contents: 'Hello, Bob!',
152
+ };
153
+
154
+ it('should return a mock signature string for typed data', async () => {
155
+ const signature = await walletClient.signTypedData({
156
+ domain,
157
+ types,
158
+ primaryType: 'Mail',
159
+ message,
160
+ account: mockAccountAddress
161
+ });
162
+ expect(signature).to.be.a('string');
163
+ expect(signature).to.match(/^0x[a-f0-9]+$/);
164
+ expect(signature).to.include(Buffer.from(`mock_signature_for_${testWalletId}_typed_Mail`).toString('hex'));
165
+ });
166
+
167
+ it('should use the account provided in parameters for typed data', async () => {
168
+ const specificAccount = '0xSpecificAccountForTypedData004';
169
+ // Spy on the signTypedData method directly
170
+ const signTypedDataSpy = sinon.spy(walletClient, 'signTypedData');
171
+ await walletClient.signTypedData({
172
+ domain,
173
+ types,
174
+ primaryType: 'Mail',
175
+ message,
176
+ account: specificAccount
177
+ });
178
+ // Verify the method was called with the specific account
179
+ expect(signTypedDataSpy.calledWith(sinon.match({
180
+ domain,
181
+ types,
182
+ primaryType: 'Mail',
183
+ message,
184
+ account: specificAccount
185
+ }))).to.be.true;
186
+ });
187
+ });
188
+
189
+ describe('sendTransaction', () => {
190
+ it('should return a mock transaction hash', async () => {
191
+ const txParams = {
192
+ account: mockAccountAddress, // Provide the account needed for sendTransaction
193
+ to: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
194
+ value: parseEther('0.01'),
195
+ chain: null // Explicitly provide chain: null when account is specified
196
+ };
197
+ // Client needs an account configured or passed for sendTransaction
198
+ const clientWithAccount = createEmblemVaultWalletClient({
199
+ sdk: sdk,
200
+ walletId: testWalletId,
201
+ account: mockAccountAddress
202
+ });
203
+ const txHash = await clientWithAccount.sendTransaction(txParams);
204
+ expect(txHash).to.be.a('string');
205
+ expect(txHash).to.match(/^0x[a-f0-9]{64}$/); // Check for 64 hex chars
206
+ });
207
+
208
+ it('should use the account provided in parameters for transaction', async () => {
209
+ const specificAccount = '0xSpecificAccountForTx005';
210
+ const txParams = {
211
+ account: specificAccount, // Pass account in tx params
212
+ to: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
213
+ value: parseEther('0.01'),
214
+ chain: null // Explicitly provide chain: null when account is specified in params
215
+ };
216
+ // Spy on the sendTransaction method directly
217
+ const sendTransactionSpy = sinon.spy(walletClient, 'sendTransaction');
218
+ await walletClient.sendTransaction(txParams); // Can use default client as account is in params
219
+ // Verify the method was called with the specific account
220
+ expect(sendTransactionSpy.calledWith(sinon.match({
221
+ account: specificAccount,
222
+ to: txParams.to,
223
+ value: txParams.value,
224
+ chain: null
225
+ }))).to.be.true;
226
+ });
227
+
228
+ it('should throw if no account is available', async () => {
229
+ const txParams = {
230
+ to: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
231
+ value: parseEther('0.01'),
232
+ };
233
+ // We need to provide an account, even if it's just the mock one, to hit the logic path being tested
234
+ // The implementation should check for account presence *before* this call is made in real scenarios
235
+ // However, the type requires it here. The check inside the method is what prevents the action.
236
+ try {
237
+ await walletClient.sendTransaction({ ...txParams, account: mockAccountAddress, chain: null }); // Added chain: null
238
+ // If it doesn't throw, fail the test
239
+ expect.fail('Cannot send transaction without an account specified.');
240
+ } catch (error) {
241
+ expect(error).to.be.instanceOf(Error);
242
+ expect(error.message).to.equal('Cannot send transaction without an account specified.');
243
+ }
244
+ });
245
+ });
246
+ });