@towns-protocol/utils 0.0.368 → 0.0.369

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.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Delegate wallet authentication utilities
3
+ *
4
+ * These functions support delegate wallet signatures where a primary wallet
5
+ * authorizes a device/delegate wallet to sign on its behalf with an expiry time.
6
+ */
7
+ /**
8
+ * Creates the hash source for delegate authorization signature
9
+ *
10
+ * @param devicePublicKey - Uncompressed public key (64 or 65 bytes)
11
+ * @param expiryEpochMs - Expiry timestamp in milliseconds (0 = no expiry)
12
+ * @returns Hash source to be signed by primary wallet
13
+ */
14
+ export declare function riverDelegateHashSrc(devicePublicKey: Uint8Array, expiryEpochMs: bigint): Uint8Array;
15
+ /**
16
+ * Converts uncompressed public key from string to Uint8Array
17
+ *
18
+ * @param publicKey - Public key string starting with '0x04' (132 chars total)
19
+ * @returns Public key as Uint8Array
20
+ */
21
+ export declare function publicKeyToUint8Array(publicKey: string): Uint8Array;
22
+ /**
23
+ * Derives Ethereum address from public key
24
+ *
25
+ * @param publicKey - Uncompressed public key (64 or 65 bytes)
26
+ * @returns 20-byte Ethereum address
27
+ */
28
+ export declare function publicKeyToAddress(publicKey: Uint8Array): Uint8Array;
29
+ /**
30
+ * Recovers the primary wallet address from a delegate signature
31
+ *
32
+ * This verifies that a delegate wallet was authorized by a primary wallet
33
+ * by recovering the primary wallet's address from the delegate authorization signature.
34
+ *
35
+ * @param params.delegatePubKey - Delegate wallet's public key (string or Uint8Array)
36
+ * @param params.delegateSig - Signature from primary wallet authorizing the delegate
37
+ * @param params.expiryEpochMs - Expiry timestamp that was signed
38
+ * @returns Primary wallet address (20 bytes)
39
+ */
40
+ export declare function recoverPublicKeyFromDelegateSig(params: {
41
+ delegatePubKey: Uint8Array | string;
42
+ delegateSig: Uint8Array;
43
+ expiryEpochMs: bigint;
44
+ }): Uint8Array;
45
+ //# sourceMappingURL=delegate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate.d.ts","sourceRoot":"","sources":["../src/delegate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkBH;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAChC,eAAe,EAAE,UAAU,EAC3B,aAAa,EAAE,MAAM,GACtB,UAAU,CAYZ;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAOnE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,CAMpE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE;IACpD,cAAc,EAAE,UAAU,GAAG,MAAM,CAAA;IACnC,WAAW,EAAE,UAAU,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;CACxB,GAAG,UAAU,CAYb"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Delegate wallet authentication utilities
3
+ *
4
+ * These functions support delegate wallet signatures where a primary wallet
5
+ * authorizes a device/delegate wallet to sign on its behalf with an expiry time.
6
+ */
7
+ import { ecrecover, fromRPCSig, hashPersonalMessage } from '@ethereumjs/util';
8
+ import { bin_fromHexString, bin_toHexString } from './binary';
9
+ import { check } from './check';
10
+ import { keccak256 } from 'ethereum-cryptography/keccak';
11
+ import { abytes } from '@noble/hashes/utils';
12
+ // Header for delegate signature 'RIVERSIG'
13
+ const RIVER_SIG_HEADER = new Uint8Array([82, 73, 86, 69, 82, 83, 73, 71]);
14
+ function bigintToUint8Array64(num, endianMode) {
15
+ const buffer = new ArrayBuffer(8);
16
+ const view = new DataView(buffer);
17
+ view.setBigInt64(0, num, endianMode === 'littleEndian'); // true for little endian
18
+ return new Uint8Array(buffer);
19
+ }
20
+ /**
21
+ * Creates the hash source for delegate authorization signature
22
+ *
23
+ * @param devicePublicKey - Uncompressed public key (64 or 65 bytes)
24
+ * @param expiryEpochMs - Expiry timestamp in milliseconds (0 = no expiry)
25
+ * @returns Hash source to be signed by primary wallet
26
+ */
27
+ export function riverDelegateHashSrc(devicePublicKey, expiryEpochMs) {
28
+ abytes(devicePublicKey);
29
+ check(expiryEpochMs >= 0, 'Expiry should be positive');
30
+ check(devicePublicKey.length === 64 || devicePublicKey.length === 65, 'Bad public key');
31
+ const expiryBytes = bigintToUint8Array64(expiryEpochMs, 'littleEndian');
32
+ const retVal = new Uint8Array(RIVER_SIG_HEADER.length + devicePublicKey.length + expiryBytes.length);
33
+ retVal.set(RIVER_SIG_HEADER);
34
+ retVal.set(devicePublicKey, RIVER_SIG_HEADER.length);
35
+ retVal.set(expiryBytes, RIVER_SIG_HEADER.length + devicePublicKey.length);
36
+ return retVal;
37
+ }
38
+ /**
39
+ * Converts uncompressed public key from string to Uint8Array
40
+ *
41
+ * @param publicKey - Public key string starting with '0x04' (132 chars total)
42
+ * @returns Public key as Uint8Array
43
+ */
44
+ export function publicKeyToUint8Array(publicKey) {
45
+ // Uncompressed public key in string form should start with '0x04'.
46
+ check(typeof publicKey === 'string' && publicKey.startsWith('0x04') && publicKey.length === 132, 'Bad public key');
47
+ return bin_fromHexString(publicKey);
48
+ }
49
+ /**
50
+ * Derives Ethereum address from public key
51
+ *
52
+ * @param publicKey - Uncompressed public key (64 or 65 bytes)
53
+ * @returns 20-byte Ethereum address
54
+ */
55
+ export function publicKeyToAddress(publicKey) {
56
+ abytes(publicKey, 64, 65);
57
+ if (publicKey.length === 65) {
58
+ publicKey = publicKey.slice(1);
59
+ }
60
+ return keccak256(publicKey).slice(-20);
61
+ }
62
+ /**
63
+ * Recovers the primary wallet address from a delegate signature
64
+ *
65
+ * This verifies that a delegate wallet was authorized by a primary wallet
66
+ * by recovering the primary wallet's address from the delegate authorization signature.
67
+ *
68
+ * @param params.delegatePubKey - Delegate wallet's public key (string or Uint8Array)
69
+ * @param params.delegateSig - Signature from primary wallet authorizing the delegate
70
+ * @param params.expiryEpochMs - Expiry timestamp that was signed
71
+ * @returns Primary wallet address (20 bytes)
72
+ */
73
+ export function recoverPublicKeyFromDelegateSig(params) {
74
+ const { delegateSig, expiryEpochMs } = params;
75
+ const delegatePubKey = typeof params.delegatePubKey === 'string'
76
+ ? publicKeyToUint8Array(params.delegatePubKey)
77
+ : params.delegatePubKey;
78
+ const hashSource = riverDelegateHashSrc(delegatePubKey, expiryEpochMs);
79
+ const hash = hashPersonalMessage(hashSource);
80
+ const { v, r, s } = fromRPCSig(('0x' + bin_toHexString(delegateSig)));
81
+ const recoveredCreatorPubKey = ecrecover(hash, v, r, s);
82
+ const recoveredCreatorAddress = Uint8Array.from(publicKeyToAddress(recoveredCreatorPubKey));
83
+ return recoveredCreatorAddress;
84
+ }
85
+ //# sourceMappingURL=delegate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../src/delegate.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  **************************************************************************/
4
4
  export * from './binary';
5
5
  export * from './check';
6
+ export * from './delegate';
6
7
  export * from './dlog';
7
8
  export * from './envUtils';
8
9
  export * from './utils';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;4EAE4E;AAC5E,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;4EAE4E;AAC5E,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  **************************************************************************/
4
4
  export * from './binary';
5
5
  export * from './check';
6
+ export * from './delegate';
6
7
  export * from './dlog';
7
8
  export * from './envUtils';
8
9
  export * from './utils';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;4EAE4E;AAC5E,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;4EAE4E;AAC5E,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@towns-protocol/utils",
3
- "version": "0.0.368",
3
+ "version": "0.0.369",
4
4
  "packageManager": "yarn@3.8.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -19,7 +19,9 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@bufbuild/protobuf": "^2.9.0",
22
- "@towns-protocol/proto": "^0.0.368",
22
+ "@ethereumjs/util": "^10.0.0",
23
+ "@noble/hashes": "^1.8.0",
24
+ "@towns-protocol/proto": "^0.0.369",
23
25
  "debug": "^4.3.4",
24
26
  "ethereum-cryptography": "^3.2.0"
25
27
  },
@@ -40,5 +42,5 @@
40
42
  "publishConfig": {
41
43
  "access": "public"
42
44
  },
43
- "gitHead": "bb014c92cd91d742be6ea53ac56027ec90e4d345"
45
+ "gitHead": "5a4adeead17c71980426b92b98c23952536e08fa"
44
46
  }