@snapshot-labs/snapshot.js 0.12.65 → 0.13.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.
@@ -155,7 +155,11 @@ declare const _default: {
155
155
  maxItems: number;
156
156
  items: {
157
157
  type: string;
158
- format: string;
158
+ anyOf: {
159
+ type: string;
160
+ format: string;
161
+ }[];
162
+ errorMessage: string;
159
163
  };
160
164
  title: string;
161
165
  uniqueItems: boolean;
@@ -165,7 +169,11 @@ declare const _default: {
165
169
  maxItems: number;
166
170
  items: {
167
171
  type: string;
168
- format: string;
172
+ anyOf: {
173
+ type: string;
174
+ format: string;
175
+ }[];
176
+ errorMessage: string;
169
177
  };
170
178
  title: string;
171
179
  uniqueItems: boolean;
@@ -175,7 +183,11 @@ declare const _default: {
175
183
  maxItems: number;
176
184
  items: {
177
185
  type: string;
178
- format: string;
186
+ anyOf: {
187
+ type: string;
188
+ format: string;
189
+ }[];
190
+ errorMessage: string;
179
191
  };
180
192
  title: string;
181
193
  uniqueItems: boolean;
@@ -270,6 +282,7 @@ declare const _default: {
270
282
  description: string;
271
283
  examples: string[];
272
284
  anyOf: {
285
+ type: string;
273
286
  format: string;
274
287
  }[];
275
288
  errorMessage: string;
@@ -378,6 +391,7 @@ declare const _default: {
378
391
  title: string;
379
392
  examples: string[];
380
393
  anyOf: {
394
+ type: string;
381
395
  format: string;
382
396
  }[];
383
397
  errorMessage: string;
@@ -151,7 +151,11 @@ declare const _default: {
151
151
  maxItems: number;
152
152
  items: {
153
153
  type: string;
154
- format: string;
154
+ anyOf: {
155
+ type: string;
156
+ format: string;
157
+ }[];
158
+ errorMessage: string;
155
159
  };
156
160
  title: string;
157
161
  uniqueItems: boolean;
@@ -161,7 +165,11 @@ declare const _default: {
161
165
  maxItems: number;
162
166
  items: {
163
167
  type: string;
164
- format: string;
168
+ anyOf: {
169
+ type: string;
170
+ format: string;
171
+ }[];
172
+ errorMessage: string;
165
173
  };
166
174
  title: string;
167
175
  uniqueItems: boolean;
@@ -171,7 +179,11 @@ declare const _default: {
171
179
  maxItems: number;
172
180
  items: {
173
181
  type: string;
174
- format: string;
182
+ anyOf: {
183
+ type: string;
184
+ format: string;
185
+ }[];
186
+ errorMessage: string;
175
187
  };
176
188
  title: string;
177
189
  uniqueItems: boolean;
@@ -266,6 +278,7 @@ declare const _default: {
266
278
  description: string;
267
279
  examples: string[];
268
280
  anyOf: {
281
+ type: string;
269
282
  format: string;
270
283
  }[];
271
284
  errorMessage: string;
@@ -374,6 +387,7 @@ declare const _default: {
374
387
  title: string;
375
388
  examples: string[];
376
389
  anyOf: {
390
+ type: string;
377
391
  format: string;
378
392
  }[];
379
393
  errorMessage: string;
@@ -38,7 +38,7 @@ export declare function sleep(time: any): Promise<unknown>;
38
38
  export declare function getNumberWithOrdinal(n: any): string;
39
39
  export declare function isStarknetAddress(address: string): boolean;
40
40
  export declare function isEvmAddress(address: string): boolean;
41
- export declare function getFormattedAddress(address: string, format: 'evm' | 'starknet'): string;
41
+ export declare function getFormattedAddress(address: string, format?: 'evm' | 'starknet'): string;
42
42
  export { getDelegatesBySpace, SNAPSHOT_SUBGRAPH_URL };
43
43
  declare const _default: {
44
44
  call: typeof call;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapshot-labs/snapshot.js",
3
- "version": "0.12.65",
3
+ "version": "0.13.1",
4
4
  "repository": "snapshot-labs/snapshot.js",
5
5
  "license": "MIT",
6
6
  "main": "dist/snapshot.cjs.js",
@@ -154,7 +154,11 @@
154
154
  "maxItems": 100,
155
155
  "items": {
156
156
  "type": "string",
157
- "format": "evmAddress"
157
+ "anyOf": [
158
+ { "type": "string", "format": "evmAddress" },
159
+ { "type": "string", "format": "starknetAddress" }
160
+ ],
161
+ "errorMessage": "Must be a valid address"
158
162
  },
159
163
  "title": "members",
160
164
  "uniqueItems": true
@@ -164,7 +168,11 @@
164
168
  "maxItems": 100,
165
169
  "items": {
166
170
  "type": "string",
167
- "format": "evmAddress"
171
+ "anyOf": [
172
+ { "type": "string", "format": "evmAddress" },
173
+ { "type": "string", "format": "starknetAddress" }
174
+ ],
175
+ "errorMessage": "Must be a valid address"
168
176
  },
169
177
  "title": "admins",
170
178
  "uniqueItems": true
@@ -174,7 +182,11 @@
174
182
  "maxItems": 100,
175
183
  "items": {
176
184
  "type": "string",
177
- "format": "evmAddress"
185
+ "anyOf": [
186
+ { "type": "string", "format": "evmAddress" },
187
+ { "type": "string", "format": "starknetAddress" }
188
+ ],
189
+ "errorMessage": "Must be a valid address"
178
190
  },
179
191
  "title": "moderators",
180
192
  "uniqueItems": true
@@ -270,8 +282,8 @@
270
282
  "description": "The address of your delegation contract",
271
283
  "examples": ["0x3901D0fDe202aF1427216b79f5243f8A022d68cf"],
272
284
  "anyOf": [
273
- { "format": "evmAddress" },
274
- { "format": "starknetAddress" }
285
+ { "type": "string", "format": "evmAddress" },
286
+ { "type": "string", "format": "starknetAddress" }
275
287
  ],
276
288
  "errorMessage": "Must be a valid EVM of Starknet address"
277
289
  },
@@ -397,8 +409,8 @@
397
409
  "title": "Contract address",
398
410
  "examples": ["e.g. 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"],
399
411
  "anyOf": [
400
- { "format": "evmAddress" },
401
- { "format": "starknetAddress" }
412
+ { "type": "string", "format": "evmAddress" },
413
+ { "type": "string", "format": "starknetAddress" }
402
414
  ],
403
415
  "errorMessage": "Must be a valid EVM of Starknet address"
404
416
  },
@@ -64,5 +64,15 @@
64
64
  "d56782e3b50ac86c25ae292923da8c367e3c9e8e7ea9d8baa435051fe2f430fa": "proposal",
65
65
  "df10a7eeabe19301d6018be8b6c5d13231320d7ece64d021043fa172b64f3796": "update-proposal",
66
66
  "beda1f464a6112f9ed6335c4614e32a97f0e18ef4ac10b4b1c8239c475f2d8e8": "proposal",
67
- "ff74674f39ca59b60056ecddaada0cb513c4729e634e99cb778f53ee404ac806": "update-proposal"
67
+ "ff74674f39ca59b60056ecddaada0cb513c4729e634e99cb778f53ee404ac806": "update-proposal",
68
+ "e037b37311c75c995f732b57cd456bdc685e5eac29668698be34388cafb14097": "proposal",
69
+ "9c66485d2c9af4010e89b0352e3f78ce2aa96661c531b1bdbd7042388867e830": "update-proposal",
70
+ "dd19ee4357e5bc813529e1b537b77ccb767135701f0223434f3b53f1ac03dcc6": "delete-proposal",
71
+ "817265460009cfdbde0752fcc7ef629ae7e05a6e8b6cbffab8a7cbf6cd19e87e": "delete-proposal",
72
+ "fb8fa9816cd42974e7f1af671aa548c8c458553364ed809e45042f141de8c0d5": "vote",
73
+ "5f95ed849bafb034c37e340dc06ad6fa6985d674714cb602a6bf11119ffba2a1": "vote-array",
74
+ "afc5911fd9722b3dc5e8b16a552997510644a52d2b229c3868fb1910b112416e": "vote-string",
75
+ "e4b768874f191321f9a6460e15f87e98800c78c1e3104f9d4e443f2ed9b1c45e": "vote",
76
+ "86c81555a3dda45aa7b151c574dc27f7402c23d9b1432156f1daa6c2e15f9891": "vote-array",
77
+ "c0f418890817b3e6deb58fa3182bf8ed7619242666a9087eab28f27a6876e1da": "vote-string"
68
78
  }
package/src/sign/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import fetch from 'cross-fetch';
2
2
  import { Web3Provider } from '@ethersproject/providers';
3
3
  import { Wallet } from '@ethersproject/wallet';
4
- import { getAddress } from '@ethersproject/address';
5
4
  import {
6
5
  Space,
7
6
  Proposal,
@@ -39,6 +38,7 @@ import {
39
38
  statementTypes
40
39
  } from './types';
41
40
  import constants from '../constants.json';
41
+ import { getFormattedAddress } from '../utils';
42
42
 
43
43
  const NAME = 'snapshot';
44
44
  const VERSION = '0.1.4';
@@ -74,8 +74,10 @@ export default class Client {
74
74
  async sign(web3: Web3Provider | Wallet, address: string, message, types) {
75
75
  // @ts-ignore
76
76
  const signer = web3?.getSigner ? web3.getSigner() : web3;
77
- const checksumAddress = getAddress(address);
78
- message.from = message.from ? getAddress(message.from) : checksumAddress;
77
+ const checksumAddress = getFormattedAddress(address, 'evm');
78
+ message.from = message.from
79
+ ? getFormattedAddress(message.from)
80
+ : checksumAddress;
79
81
  if (!message.timestamp)
80
82
  message.timestamp = parseInt((Date.now() / 1e3).toFixed());
81
83
 
package/src/sign/types.ts CHANGED
@@ -139,7 +139,7 @@ export const spaceTypes = {
139
139
 
140
140
  export const proposalTypes = {
141
141
  Proposal: [
142
- { name: 'from', type: 'address' },
142
+ { name: 'from', type: 'string' },
143
143
  { name: 'space', type: 'string' },
144
144
  { name: 'timestamp', type: 'uint64' },
145
145
  { name: 'type', type: 'string' },
@@ -160,7 +160,7 @@ export const proposalTypes = {
160
160
  export const updateProposalTypes = {
161
161
  UpdateProposal: [
162
162
  { name: 'proposal', type: 'string' },
163
- { name: 'from', type: 'address' },
163
+ { name: 'from', type: 'string' },
164
164
  { name: 'space', type: 'string' },
165
165
  { name: 'timestamp', type: 'uint64' },
166
166
  { name: 'type', type: 'string' },
@@ -185,7 +185,7 @@ export const flagProposalTypes = {
185
185
 
186
186
  export const cancelProposalTypes = {
187
187
  CancelProposal: [
188
- { name: 'from', type: 'address' },
188
+ { name: 'from', type: 'string' },
189
189
  { name: 'space', type: 'string' },
190
190
  { name: 'timestamp', type: 'uint64' },
191
191
  { name: 'proposal', type: 'string' }
@@ -194,7 +194,7 @@ export const cancelProposalTypes = {
194
194
 
195
195
  export const cancelProposal2Types = {
196
196
  CancelProposal: [
197
- { name: 'from', type: 'address' },
197
+ { name: 'from', type: 'string' },
198
198
  { name: 'space', type: 'string' },
199
199
  { name: 'timestamp', type: 'uint64' },
200
200
  { name: 'proposal', type: 'bytes32' }
@@ -203,7 +203,7 @@ export const cancelProposal2Types = {
203
203
 
204
204
  export const voteTypes = {
205
205
  Vote: [
206
- { name: 'from', type: 'address' },
206
+ { name: 'from', type: 'string' },
207
207
  { name: 'space', type: 'string' },
208
208
  { name: 'timestamp', type: 'uint64' },
209
209
  { name: 'proposal', type: 'string' },
@@ -216,7 +216,7 @@ export const voteTypes = {
216
216
 
217
217
  export const voteArrayTypes = {
218
218
  Vote: [
219
- { name: 'from', type: 'address' },
219
+ { name: 'from', type: 'string' },
220
220
  { name: 'space', type: 'string' },
221
221
  { name: 'timestamp', type: 'uint64' },
222
222
  { name: 'proposal', type: 'string' },
@@ -229,7 +229,7 @@ export const voteArrayTypes = {
229
229
 
230
230
  export const voteStringTypes = {
231
231
  Vote: [
232
- { name: 'from', type: 'address' },
232
+ { name: 'from', type: 'string' },
233
233
  { name: 'space', type: 'string' },
234
234
  { name: 'timestamp', type: 'uint64' },
235
235
  { name: 'proposal', type: 'string' },
@@ -242,7 +242,7 @@ export const voteStringTypes = {
242
242
 
243
243
  export const vote2Types = {
244
244
  Vote: [
245
- { name: 'from', type: 'address' },
245
+ { name: 'from', type: 'string' },
246
246
  { name: 'space', type: 'string' },
247
247
  { name: 'timestamp', type: 'uint64' },
248
248
  { name: 'proposal', type: 'bytes32' },
@@ -255,7 +255,7 @@ export const vote2Types = {
255
255
 
256
256
  export const voteArray2Types = {
257
257
  Vote: [
258
- { name: 'from', type: 'address' },
258
+ { name: 'from', type: 'string' },
259
259
  { name: 'space', type: 'string' },
260
260
  { name: 'timestamp', type: 'uint64' },
261
261
  { name: 'proposal', type: 'bytes32' },
@@ -268,7 +268,7 @@ export const voteArray2Types = {
268
268
 
269
269
  export const voteString2Types = {
270
270
  Vote: [
271
- { name: 'from', type: 'address' },
271
+ { name: 'from', type: 'string' },
272
272
  { name: 'space', type: 'string' },
273
273
  { name: 'timestamp', type: 'uint64' },
274
274
  { name: 'proposal', type: 'bytes32' },
package/src/utils.spec.js CHANGED
@@ -504,37 +504,269 @@ describe('utils', () => {
504
504
  });
505
505
 
506
506
  describe('getFormattedAddress', () => {
507
- test('returns a checksummed EVM address', () => {
508
- const address = '0x91fd2c8d24767db4ece7069aa27832ffaf8590f3';
509
- expect(getFormattedAddress(address, 'evm')).toEqual(
510
- '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
511
- );
512
- });
507
+ describe('when explicitly passing an address type', () => {
508
+ describe('EVM type parsing', () => {
509
+ test('should return checksummed EVM address when given checksummed input', () => {
510
+ const address = '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3';
511
+ expect(getFormattedAddress(address, 'evm')).toEqual(
512
+ '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
513
+ );
514
+ });
513
515
 
514
- test('returns a padded and lowercased starknet address', () => {
515
- const address =
516
- '0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
517
- expect(getFormattedAddress(address, 'starknet')).toEqual(
518
- '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
519
- );
520
- });
516
+ test('should return checksummed EVM address when given lowercase input', () => {
517
+ const address = '0x91fd2c8d24767db4ece7069aa27832ffaf8590f3';
518
+ expect(getFormattedAddress(address, 'evm')).toEqual(
519
+ '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
520
+ );
521
+ });
521
522
 
522
- test('returns an EVM address as starknet address', () => {
523
- const address = '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3';
524
- expect(getFormattedAddress(address, 'starknet')).toEqual(
525
- '0x00000000000000000000000091fd2c8d24767db4ece7069aa27832ffaf8590f3'
526
- );
527
- });
523
+ test('should return checksummed EVM address when given uppercase input', () => {
524
+ const uppercaseAddress = '0x91FD2C8D24767DB4ECE7069AA27832FFAF8590F3';
525
+ expect(getFormattedAddress(uppercaseAddress, 'evm')).toEqual(
526
+ '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
527
+ );
528
+ });
528
529
 
529
- test('throws an error when the address is not a starknet address', () => {
530
- const address = 'hello';
531
- expect(() => getFormattedAddress(address, 'starknet')).toThrow();
530
+ test('should throw error when forcing EVM parsing on address with uppercase 0X prefix', () => {
531
+ const uppercaseHexPrefix =
532
+ '0X91FD2C8D24767DB4ECE7069AA27832FFAF8590F3';
533
+ expect(() => getFormattedAddress(uppercaseHexPrefix, 'evm')).toThrow(
534
+ 'Invalid evm address: 0X91FD2C8D24767DB4ECE7069AA27832FFAF8590F3'
535
+ );
536
+ });
537
+
538
+ test('should throw error when forcing EVM parsing on invalid mixed case address', () => {
539
+ const invalidMixedCaseAddress =
540
+ '0x91Fd2C8d24767Db4eCe7069aA27832FfaF8590F3';
541
+ expect(() =>
542
+ getFormattedAddress(invalidMixedCaseAddress, 'evm')
543
+ ).toThrow(
544
+ 'Invalid evm address: 0x91Fd2C8d24767Db4eCe7069aA27832FfaF8590F3'
545
+ );
546
+ });
547
+
548
+ test('should throw error when address is not an EVM address', () => {
549
+ const address =
550
+ '0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
551
+ expect(() => getFormattedAddress(address, 'evm')).toThrow(
552
+ 'Invalid evm address: 0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
553
+ );
554
+ });
555
+ });
556
+
557
+ describe('Starknet type parsing', () => {
558
+ test('should return padded and lowercased starknet address when given unpadded input', () => {
559
+ const address =
560
+ '0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
561
+ expect(getFormattedAddress(address, 'starknet')).toEqual(
562
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
563
+ );
564
+ });
565
+
566
+ test('should return padded and lowercased starknet address when given lowercase input', () => {
567
+ const address =
568
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
569
+ expect(getFormattedAddress(address, 'starknet')).toEqual(
570
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
571
+ );
572
+ });
573
+
574
+ test('should return padded and lowercased starknet address when given uppercase Starknet input', () => {
575
+ const uppercaseAddress =
576
+ '0x02A0A8F3B6097E7A6BD7649DEB30715323072A159C0E6B71B689BD245C146CC0';
577
+ expect(getFormattedAddress(uppercaseAddress, 'starknet')).toEqual(
578
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
579
+ );
580
+ });
581
+
582
+ test('should return padded and lowercased starknet address when given checksum Starknet input', () => {
583
+ const checksumAddress =
584
+ '0x02a0a8F3B6097e7A6bd7649DEB30715323072A159c0E6B71B689Bd245c146cC0';
585
+ expect(getFormattedAddress(checksumAddress, 'starknet')).toEqual(
586
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
587
+ );
588
+ });
589
+
590
+ test('should return padded and lowercased starknet address when given mixed case Starknet input', () => {
591
+ const mixedCaseAddress =
592
+ '0x02A0a8F3B6097e7A6bD7649DEB30715323072a159C0e6b71B689BD245c146Cc0';
593
+ expect(getFormattedAddress(mixedCaseAddress, 'starknet')).toEqual(
594
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
595
+ );
596
+ });
597
+
598
+ test('should return EVM address as starknet address when explicitly formatted', () => {
599
+ const address = '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3';
600
+ expect(getFormattedAddress(address, 'starknet')).toEqual(
601
+ '0x00000000000000000000000091fd2c8d24767db4ece7069aa27832ffaf8590f3'
602
+ );
603
+ });
604
+
605
+ test('should throw error when given invalid Starknet address with explicit format', () => {
606
+ const invalidStarknetAddress = '0xinvalidstarknetaddresshere';
607
+ expect(() =>
608
+ getFormattedAddress(invalidStarknetAddress, 'starknet')
609
+ ).toThrow('Invalid starknet address: 0xinvalidstarknetaddresshere');
610
+ });
611
+ });
532
612
  });
533
613
 
534
- test('throws an error when the address is not an EVM address', () => {
535
- const address =
536
- '0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
537
- expect(() => getFormattedAddress(address, 'evm')).toThrow();
614
+ describe('when not passing an address type', () => {
615
+ describe('EVM address auto-detection', () => {
616
+ test('should auto-detect and format valid 42-char lowercase EVM address', () => {
617
+ const address = '0x91fd2c8d24767db4ece7069aa27832ffaf8590f3';
618
+ expect(getFormattedAddress(address)).toEqual(
619
+ '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
620
+ );
621
+ });
622
+
623
+ test('should auto-detect and format valid 42-char uppercase EVM address', () => {
624
+ const address = '0x91FD2C8D24767DB4ECE7069AA27832FFAF8590F3';
625
+ expect(getFormattedAddress(address)).toEqual(
626
+ '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
627
+ );
628
+ });
629
+
630
+ test('should auto-detect and format valid 42-char checksummed EVM address', () => {
631
+ const address = '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3';
632
+ expect(getFormattedAddress(address)).toEqual(
633
+ '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
634
+ );
635
+ });
636
+
637
+ test('should throw error when auto-detecting invalid mixed case EVM address', () => {
638
+ const invalidMixedCaseAddress =
639
+ '0x91Fd2C8d24767Db4eCe7069aA27832FfaF8590F3';
640
+ expect(() => getFormattedAddress(invalidMixedCaseAddress)).toThrow(
641
+ 'Invalid evm address: 0x91Fd2C8d24767Db4eCe7069aA27832FfaF8590F3'
642
+ );
643
+ });
644
+
645
+ test('should throw error when auto-detecting 42-char invalid hex address', () => {
646
+ const invalidHexAddress =
647
+ '0xgggggggggggggggggggggggggggggggggggggggg';
648
+ expect(() => getFormattedAddress(invalidHexAddress)).toThrow(
649
+ 'Invalid evm address: 0xgggggggggggggggggggggggggggggggggggggggg'
650
+ );
651
+ });
652
+
653
+ test('should throw error when auto-detecting EVM address with uppercase 0X prefix', () => {
654
+ const uppercaseHexPrefix =
655
+ '0X91FD2C8D24767DB4ECE7069AA27832FFAF8590F3';
656
+ expect(() => getFormattedAddress(uppercaseHexPrefix)).toThrow(
657
+ 'Invalid evm address: 0X91FD2C8D24767DB4ECE7069AA27832FFAF8590F3'
658
+ );
659
+ });
660
+ });
661
+
662
+ describe('Starknet address auto-detection', () => {
663
+ test('should auto-detect and format valid unpadded Starknet address', () => {
664
+ const address =
665
+ '0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
666
+ expect(getFormattedAddress(address)).toEqual(
667
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
668
+ );
669
+ });
670
+
671
+ test('should auto-detect and format valid padded Starknet address', () => {
672
+ const address =
673
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
674
+ expect(getFormattedAddress(address)).toEqual(
675
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
676
+ );
677
+ });
678
+
679
+ test('should auto-detect and format uppercase Starknet address', () => {
680
+ const address =
681
+ '0x02A0A8F3B6097E7A6BD7649DEB30715323072A159C0E6B71B689BD245C146CC0';
682
+ expect(getFormattedAddress(address)).toEqual(
683
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
684
+ );
685
+ });
686
+
687
+ test('should return padded and lowercased address when input has uppercase 0X prefix', () => {
688
+ const fullyUppercaseAddress =
689
+ '0X02A0A8F3B6097E7A6BD7649DEB30715323072A159C0E6B71B689BD245C146CC0';
690
+ expect(getFormattedAddress(fullyUppercaseAddress)).toEqual(
691
+ '0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
692
+ );
693
+ });
694
+
695
+ test('should return padded and lowercased address when given short input', () => {
696
+ const address = '0x1';
697
+ expect(getFormattedAddress(address)).toEqual(
698
+ '0x0000000000000000000000000000000000000000000000000000000000000001'
699
+ );
700
+ });
701
+
702
+ test('should auto-detect actual 41-char address as Starknet', () => {
703
+ const address = '0x123456789012345678901234567890123456789';
704
+ expect(getFormattedAddress(address)).toEqual(
705
+ '0x0000000000000000000000000123456789012345678901234567890123456789'
706
+ );
707
+ });
708
+
709
+ test('should auto-detect 43+ char address as Starknet', () => {
710
+ const address = '0x123456789012345678901234567890123456789012';
711
+ expect(getFormattedAddress(address)).toEqual(
712
+ '0x0000000000000000000000123456789012345678901234567890123456789012'
713
+ );
714
+ });
715
+ });
716
+
717
+ describe('Invalid address format', () => {
718
+ test('should throw error when passing invalid format argument', () => {
719
+ const validAddress = '0x91fd2c8d24767db4ece7069aa27832ffaf8590f3';
720
+ expect(() => getFormattedAddress(validAddress, 'invalid')).toThrow(
721
+ 'Invalid invalid address: 0x91fd2c8d24767db4ece7069aa27832ffaf8590f3'
722
+ );
723
+ });
724
+
725
+ test('should treat undefined format parameter as auto-detection', () => {
726
+ const evmAddress = '0x91fd2c8d24767db4ece7069aa27832ffaf8590f3';
727
+ expect(getFormattedAddress(evmAddress, undefined)).toEqual(
728
+ '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
729
+ );
730
+ });
731
+
732
+ test('should throw error when parsing invalid string', () => {
733
+ const invalidString = 'hello';
734
+ expect(() => getFormattedAddress(invalidString)).toThrow(
735
+ 'Invalid address: hello'
736
+ );
737
+ });
738
+
739
+ test('should throw error when parsing empty string', () => {
740
+ const emptyString = '';
741
+ expect(() => getFormattedAddress(emptyString)).toThrow(
742
+ 'Invalid address: '
743
+ );
744
+ });
745
+
746
+ test('should throw error when parsing null input', () => {
747
+ expect(() => getFormattedAddress(null)).toThrow(
748
+ 'Invalid address: null'
749
+ );
750
+ });
751
+
752
+ test('should throw error when parsing undefined input', () => {
753
+ expect(() => getFormattedAddress(undefined)).toThrow(
754
+ 'Invalid address: undefined'
755
+ );
756
+ });
757
+
758
+ test('should throw error when parsing number input', () => {
759
+ expect(() => getFormattedAddress(123)).toThrow(
760
+ 'Invalid address: 123'
761
+ );
762
+ });
763
+
764
+ test('should throw error when parsing object input', () => {
765
+ expect(() => getFormattedAddress({})).toThrow(
766
+ 'Invalid address: [object Object]'
767
+ );
768
+ });
769
+ });
538
770
  });
539
771
  });
540
772
 
package/src/utils.ts CHANGED
@@ -828,13 +828,20 @@ export function isEvmAddress(address: string): boolean {
828
828
 
829
829
  export function getFormattedAddress(
830
830
  address: string,
831
- format: 'evm' | 'starknet'
831
+ format?: 'evm' | 'starknet'
832
832
  ): string {
833
- if (format === 'evm' && isEvmAddress(address)) return getAddress(address);
834
- if (format === 'starknet' && isStarknetAddress(address))
833
+ if (typeof address !== 'string' || !/^0[xX]/.test(address)) {
834
+ throw new Error(`Invalid address: ${address}`);
835
+ }
836
+
837
+ const addressType = format ?? (address.length === 42 ? 'evm' : 'starknet');
838
+
839
+ if (addressType === 'evm' && isEvmAddress(address))
840
+ return getAddress(address);
841
+ if (addressType === 'starknet' && isStarknetAddress(address))
835
842
  return validateAndParseAddress(address);
836
843
 
837
- throw new Error(`Invalid address: ${address}`);
844
+ throw new Error(`Invalid ${addressType} address: ${address}`);
838
845
  }
839
846
 
840
847
  function inputError(message: string) {