@verbeth/sdk 0.1.4 → 0.1.6

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 (190) hide show
  1. package/README.md +20 -168
  2. package/dist/esm/src/addresses.d.ts +20 -0
  3. package/dist/esm/src/addresses.d.ts.map +1 -0
  4. package/dist/esm/src/addresses.js +33 -0
  5. package/dist/esm/src/client/HsrTagIndex.d.ts +77 -0
  6. package/dist/esm/src/client/HsrTagIndex.d.ts.map +1 -0
  7. package/dist/esm/src/client/HsrTagIndex.js +157 -0
  8. package/dist/esm/src/client/PendingManager.d.ts +65 -0
  9. package/dist/esm/src/client/PendingManager.d.ts.map +1 -0
  10. package/dist/esm/src/client/PendingManager.js +84 -0
  11. package/dist/esm/src/client/SessionManager.d.ts +65 -0
  12. package/dist/esm/src/client/SessionManager.d.ts.map +1 -0
  13. package/dist/esm/src/client/SessionManager.js +146 -0
  14. package/dist/esm/src/client/VerbethClient.d.ts +153 -99
  15. package/dist/esm/src/client/VerbethClient.d.ts.map +1 -1
  16. package/dist/esm/src/client/VerbethClient.js +429 -123
  17. package/dist/esm/src/client/VerbethClientBuilder.d.ts +105 -0
  18. package/dist/esm/src/client/VerbethClientBuilder.d.ts.map +1 -0
  19. package/dist/esm/src/client/VerbethClientBuilder.js +146 -0
  20. package/dist/esm/src/client/hsrMatcher.d.ts +22 -0
  21. package/dist/esm/src/client/hsrMatcher.d.ts.map +1 -0
  22. package/dist/esm/src/client/hsrMatcher.js +31 -0
  23. package/dist/esm/src/client/index.d.ts +6 -1
  24. package/dist/esm/src/client/index.d.ts.map +1 -1
  25. package/dist/esm/src/client/index.js +2 -0
  26. package/dist/esm/src/client/types.d.ts +151 -10
  27. package/dist/esm/src/client/types.d.ts.map +1 -1
  28. package/dist/esm/src/crypto(old).d.ts +46 -0
  29. package/dist/esm/src/crypto(old).d.ts.map +1 -0
  30. package/dist/esm/src/crypto(old).js +137 -0
  31. package/dist/esm/src/crypto.d.ts +7 -29
  32. package/dist/esm/src/crypto.d.ts.map +1 -1
  33. package/dist/esm/src/crypto.js +36 -72
  34. package/dist/esm/src/executor.d.ts +17 -18
  35. package/dist/esm/src/executor.d.ts.map +1 -1
  36. package/dist/esm/src/executor.js +54 -70
  37. package/dist/esm/src/handshake.d.ts +51 -0
  38. package/dist/esm/src/handshake.d.ts.map +1 -0
  39. package/dist/esm/src/handshake.js +105 -0
  40. package/dist/esm/src/identity.d.ts +24 -18
  41. package/dist/esm/src/identity.d.ts.map +1 -1
  42. package/dist/esm/src/identity.js +126 -31
  43. package/dist/esm/src/index.d.ts +11 -7
  44. package/dist/esm/src/index.d.ts.map +1 -1
  45. package/dist/esm/src/index.js +10 -7
  46. package/dist/esm/src/payload.d.ts +3 -30
  47. package/dist/esm/src/payload.d.ts.map +1 -1
  48. package/dist/esm/src/payload.js +3 -77
  49. package/dist/esm/src/pq/kem.d.ts +33 -0
  50. package/dist/esm/src/pq/kem.d.ts.map +1 -0
  51. package/dist/esm/src/pq/kem.js +40 -0
  52. package/dist/esm/src/ratchet/auth.d.ts +34 -0
  53. package/dist/esm/src/ratchet/auth.d.ts.map +1 -0
  54. package/dist/esm/src/ratchet/auth.js +88 -0
  55. package/dist/esm/src/ratchet/codec.d.ts +52 -0
  56. package/dist/esm/src/ratchet/codec.d.ts.map +1 -0
  57. package/dist/esm/src/ratchet/codec.js +127 -0
  58. package/dist/esm/src/ratchet/decrypt.d.ts +28 -0
  59. package/dist/esm/src/ratchet/decrypt.d.ts.map +1 -0
  60. package/dist/esm/src/ratchet/decrypt.js +255 -0
  61. package/dist/esm/src/ratchet/encrypt.d.ts +17 -0
  62. package/dist/esm/src/ratchet/encrypt.d.ts.map +1 -0
  63. package/dist/esm/src/ratchet/encrypt.js +78 -0
  64. package/dist/esm/src/ratchet/index.d.ts +8 -0
  65. package/dist/esm/src/ratchet/index.d.ts.map +1 -0
  66. package/dist/esm/src/ratchet/index.js +8 -0
  67. package/dist/esm/src/ratchet/kdf.d.ts +60 -0
  68. package/dist/esm/src/ratchet/kdf.d.ts.map +1 -0
  69. package/dist/esm/src/ratchet/kdf.js +91 -0
  70. package/dist/esm/src/ratchet/session.d.ts +43 -0
  71. package/dist/esm/src/ratchet/session.d.ts.map +1 -0
  72. package/dist/esm/src/ratchet/session.js +139 -0
  73. package/dist/esm/src/ratchet/types.d.ts +168 -0
  74. package/dist/esm/src/ratchet/types.d.ts.map +1 -0
  75. package/dist/esm/src/ratchet/types.js +27 -0
  76. package/dist/esm/src/safeSessionSigner.d.ts +35 -0
  77. package/dist/esm/src/safeSessionSigner.d.ts.map +1 -0
  78. package/dist/esm/src/safeSessionSigner.js +59 -0
  79. package/dist/esm/src/send.d.ts +32 -24
  80. package/dist/esm/src/send.d.ts.map +1 -1
  81. package/dist/esm/src/send.js +84 -39
  82. package/dist/esm/src/types.d.ts +8 -13
  83. package/dist/esm/src/types.d.ts.map +1 -1
  84. package/dist/esm/src/utils/safeSessionSigner.d.ts +23 -0
  85. package/dist/esm/src/utils/safeSessionSigner.d.ts.map +1 -0
  86. package/dist/esm/src/utils/safeSessionSigner.js +59 -0
  87. package/dist/esm/src/utils/txQueue.d.ts +12 -0
  88. package/dist/esm/src/utils/txQueue.d.ts.map +1 -0
  89. package/dist/esm/src/utils/txQueue.js +25 -0
  90. package/dist/esm/src/utils.d.ts +2 -3
  91. package/dist/esm/src/utils.d.ts.map +1 -1
  92. package/dist/esm/src/utils.js +5 -5
  93. package/dist/esm/src/verify.d.ts +9 -25
  94. package/dist/esm/src/verify.d.ts.map +1 -1
  95. package/dist/esm/src/verify.js +49 -50
  96. package/dist/src/addresses.d.ts +20 -0
  97. package/dist/src/addresses.d.ts.map +1 -0
  98. package/dist/src/addresses.js +33 -0
  99. package/dist/src/client/HsrTagIndex.d.ts +77 -0
  100. package/dist/src/client/HsrTagIndex.d.ts.map +1 -0
  101. package/dist/src/client/HsrTagIndex.js +157 -0
  102. package/dist/src/client/PendingManager.d.ts +65 -0
  103. package/dist/src/client/PendingManager.d.ts.map +1 -0
  104. package/dist/src/client/PendingManager.js +84 -0
  105. package/dist/src/client/SessionManager.d.ts +65 -0
  106. package/dist/src/client/SessionManager.d.ts.map +1 -0
  107. package/dist/src/client/SessionManager.js +146 -0
  108. package/dist/src/client/VerbethClient.d.ts +153 -99
  109. package/dist/src/client/VerbethClient.d.ts.map +1 -1
  110. package/dist/src/client/VerbethClient.js +429 -123
  111. package/dist/src/client/VerbethClientBuilder.d.ts +105 -0
  112. package/dist/src/client/VerbethClientBuilder.d.ts.map +1 -0
  113. package/dist/src/client/VerbethClientBuilder.js +146 -0
  114. package/dist/src/client/hsrMatcher.d.ts +22 -0
  115. package/dist/src/client/hsrMatcher.d.ts.map +1 -0
  116. package/dist/src/client/hsrMatcher.js +31 -0
  117. package/dist/src/client/index.d.ts +6 -1
  118. package/dist/src/client/index.d.ts.map +1 -1
  119. package/dist/src/client/index.js +2 -0
  120. package/dist/src/client/types.d.ts +151 -10
  121. package/dist/src/client/types.d.ts.map +1 -1
  122. package/dist/src/crypto(old).d.ts +46 -0
  123. package/dist/src/crypto(old).d.ts.map +1 -0
  124. package/dist/src/crypto(old).js +137 -0
  125. package/dist/src/crypto.d.ts +7 -29
  126. package/dist/src/crypto.d.ts.map +1 -1
  127. package/dist/src/crypto.js +36 -72
  128. package/dist/src/executor.d.ts +17 -18
  129. package/dist/src/executor.d.ts.map +1 -1
  130. package/dist/src/executor.js +54 -70
  131. package/dist/src/handshake.d.ts +51 -0
  132. package/dist/src/handshake.d.ts.map +1 -0
  133. package/dist/src/handshake.js +105 -0
  134. package/dist/src/identity.d.ts +24 -18
  135. package/dist/src/identity.d.ts.map +1 -1
  136. package/dist/src/identity.js +126 -31
  137. package/dist/src/index.d.ts +11 -7
  138. package/dist/src/index.d.ts.map +1 -1
  139. package/dist/src/index.js +10 -7
  140. package/dist/src/payload.d.ts +3 -30
  141. package/dist/src/payload.d.ts.map +1 -1
  142. package/dist/src/payload.js +3 -77
  143. package/dist/src/pq/kem.d.ts +33 -0
  144. package/dist/src/pq/kem.d.ts.map +1 -0
  145. package/dist/src/pq/kem.js +40 -0
  146. package/dist/src/ratchet/auth.d.ts +34 -0
  147. package/dist/src/ratchet/auth.d.ts.map +1 -0
  148. package/dist/src/ratchet/auth.js +88 -0
  149. package/dist/src/ratchet/codec.d.ts +52 -0
  150. package/dist/src/ratchet/codec.d.ts.map +1 -0
  151. package/dist/src/ratchet/codec.js +127 -0
  152. package/dist/src/ratchet/decrypt.d.ts +28 -0
  153. package/dist/src/ratchet/decrypt.d.ts.map +1 -0
  154. package/dist/src/ratchet/decrypt.js +255 -0
  155. package/dist/src/ratchet/encrypt.d.ts +17 -0
  156. package/dist/src/ratchet/encrypt.d.ts.map +1 -0
  157. package/dist/src/ratchet/encrypt.js +78 -0
  158. package/dist/src/ratchet/index.d.ts +8 -0
  159. package/dist/src/ratchet/index.d.ts.map +1 -0
  160. package/dist/src/ratchet/index.js +8 -0
  161. package/dist/src/ratchet/kdf.d.ts +60 -0
  162. package/dist/src/ratchet/kdf.d.ts.map +1 -0
  163. package/dist/src/ratchet/kdf.js +91 -0
  164. package/dist/src/ratchet/session.d.ts +43 -0
  165. package/dist/src/ratchet/session.d.ts.map +1 -0
  166. package/dist/src/ratchet/session.js +139 -0
  167. package/dist/src/ratchet/types.d.ts +168 -0
  168. package/dist/src/ratchet/types.d.ts.map +1 -0
  169. package/dist/src/ratchet/types.js +27 -0
  170. package/dist/src/safeSessionSigner.d.ts +35 -0
  171. package/dist/src/safeSessionSigner.d.ts.map +1 -0
  172. package/dist/src/safeSessionSigner.js +59 -0
  173. package/dist/src/send.d.ts +32 -24
  174. package/dist/src/send.d.ts.map +1 -1
  175. package/dist/src/send.js +84 -39
  176. package/dist/src/types.d.ts +8 -13
  177. package/dist/src/types.d.ts.map +1 -1
  178. package/dist/src/utils/safeSessionSigner.d.ts +23 -0
  179. package/dist/src/utils/safeSessionSigner.d.ts.map +1 -0
  180. package/dist/src/utils/safeSessionSigner.js +59 -0
  181. package/dist/src/utils/txQueue.d.ts +12 -0
  182. package/dist/src/utils/txQueue.d.ts.map +1 -0
  183. package/dist/src/utils/txQueue.js +25 -0
  184. package/dist/src/utils.d.ts +2 -3
  185. package/dist/src/utils.d.ts.map +1 -1
  186. package/dist/src/utils.js +5 -5
  187. package/dist/src/verify.d.ts +9 -25
  188. package/dist/src/verify.d.ts.map +1 -1
  189. package/dist/src/verify.js +49 -50
  190. package/package.json +2 -1
@@ -3,7 +3,6 @@ import { Interface, toBeHex, zeroPadValue, } from "ethers";
3
3
  function pack128x128(high, low) {
4
4
  return (high << 128n) | (low & ((1n << 128n) - 1n));
5
5
  }
6
- // Unpack a packed 256-bit value into two 128-bit values
7
6
  export function split128x128(word) {
8
7
  const lowMask = (1n << 128n) - 1n;
9
8
  return [word >> 128n, word & lowMask];
@@ -47,18 +46,16 @@ export class EOAExecutor {
47
46
  }
48
47
  // Base Smart Account Executor - Uses wallet_sendCalls for sponsored transactions
49
48
  export class BaseSmartAccountExecutor {
50
- constructor(baseAccountProvider, logChainAddress, chainId = 8453, // Base mainnet by default
51
- paymasterServiceUrl, subAccountAddress) {
49
+ constructor(baseAccountProvider, verbEthAddress, chainId = 8453, paymasterServiceUrl, subAccountAddress) {
52
50
  this.baseAccountProvider = baseAccountProvider;
53
- this.logChainAddress = logChainAddress;
51
+ this.verbEthAddress = verbEthAddress;
54
52
  this.paymasterServiceUrl = paymasterServiceUrl;
55
53
  this.subAccountAddress = subAccountAddress;
56
- this.logChainInterface = new Interface([
54
+ this.verbEthInterface = new Interface([
57
55
  "function sendMessage(bytes calldata ciphertext, bytes32 topic, uint256 timestamp, uint256 nonce)",
58
56
  "function initiateHandshake(bytes32 recipientHash, bytes pubKeys, bytes ephemeralPubKey, bytes plaintextPayload)",
59
57
  "function respondToHandshake(bytes32 inResponseTo, bytes32 responderEphemeralR, bytes ciphertext)",
60
58
  ]);
61
- // Convert chainId to hex
62
59
  this.chainId =
63
60
  chainId === 8453
64
61
  ? "0x2105" // Base mainnet
@@ -67,7 +64,7 @@ export class BaseSmartAccountExecutor {
67
64
  : `0x${chainId.toString(16)}`;
68
65
  }
69
66
  async sendMessage(ciphertext, topic, timestamp, nonce) {
70
- const callData = this.logChainInterface.encodeFunctionData("sendMessage", [
67
+ const callData = this.verbEthInterface.encodeFunctionData("sendMessage", [
71
68
  ciphertext,
72
69
  topic,
73
70
  timestamp,
@@ -75,27 +72,27 @@ export class BaseSmartAccountExecutor {
75
72
  ]);
76
73
  return this.executeCalls([
77
74
  {
78
- to: this.logChainAddress,
75
+ to: this.verbEthAddress,
79
76
  value: "0x0",
80
77
  data: callData,
81
78
  },
82
79
  ]);
83
80
  }
84
81
  async initiateHandshake(recipientHash, pubKeys, ephemeralPubKey, plaintextPayload) {
85
- const callData = this.logChainInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
82
+ const callData = this.verbEthInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
86
83
  return this.executeCalls([
87
84
  {
88
- to: this.logChainAddress,
85
+ to: this.verbEthAddress,
89
86
  value: "0x0",
90
87
  data: callData,
91
88
  },
92
89
  ]);
93
90
  }
94
91
  async respondToHandshake(inResponseTo, responderEphemeralR, ciphertext) {
95
- const callData = this.logChainInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
92
+ const callData = this.verbEthInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
96
93
  return this.executeCalls([
97
94
  {
98
- to: this.logChainAddress,
95
+ to: this.verbEthAddress,
99
96
  value: "0x0",
100
97
  data: callData,
101
98
  },
@@ -103,7 +100,6 @@ export class BaseSmartAccountExecutor {
103
100
  }
104
101
  async executeCalls(calls) {
105
102
  try {
106
- //console.log("DEBUG: Sub account address:", this.subAccountAddress);
107
103
  const requestParams = {
108
104
  version: "1.0",
109
105
  chainId: this.chainId,
@@ -112,7 +108,6 @@ export class BaseSmartAccountExecutor {
112
108
  //** WORK IN PROGRESS */
113
109
  if (this.subAccountAddress) {
114
110
  requestParams.from = this.subAccountAddress;
115
- //console.log("DEBUG: Using sub account for transaction");
116
111
  }
117
112
  if (this.paymasterServiceUrl) {
118
113
  requestParams.capabilities = {
@@ -120,19 +115,15 @@ export class BaseSmartAccountExecutor {
120
115
  url: this.paymasterServiceUrl,
121
116
  },
122
117
  };
123
- //console.log("DEBUG: Using paymaster for gas sponsorship");
124
118
  }
125
- //console.log("DEBUG: Request params:", requestParams);
126
119
  const result = await this.baseAccountProvider.request({
127
120
  method: "wallet_sendCalls",
128
121
  params: [requestParams],
129
122
  });
130
- // first 32 bytes are the actual userop hash
131
123
  if (typeof result === "string" &&
132
124
  result.startsWith("0x") &&
133
125
  result.length > 66) {
134
- const actualTxHash = "0x" + result.slice(2, 66); // Extract first 32 bytes
135
- //console.log("DEBUG: extracted tx hash:", actualTxHash);
126
+ const actualTxHash = "0x" + result.slice(2, 66);
136
127
  return { hash: actualTxHash };
137
128
  }
138
129
  return result;
@@ -145,45 +136,44 @@ export class BaseSmartAccountExecutor {
145
136
  }
146
137
  // UserOp Executor - Account Abstraction via bundler
147
138
  export class UserOpExecutor {
148
- constructor(smartAccountAddress, logChainAddress, bundlerClient, smartAccountClient) {
139
+ constructor(smartAccountAddress, verbEthAddress, bundlerClient, smartAccountClient) {
149
140
  this.smartAccountAddress = smartAccountAddress;
150
- this.logChainAddress = logChainAddress;
141
+ this.verbEthAddress = verbEthAddress;
151
142
  this.bundlerClient = bundlerClient;
152
143
  this.smartAccountClient = smartAccountClient;
153
- this.logChainInterface = new Interface([
144
+ this.verbEthInterface = new Interface([
154
145
  "function sendMessage(bytes calldata ciphertext, bytes32 topic, uint256 timestamp, uint256 nonce)",
155
146
  "function initiateHandshake(bytes32 recipientHash, bytes pubKeys, bytes ephemeralPubKey, bytes plaintextPayload)",
156
147
  "function respondToHandshake(bytes32 inResponseTo, bytes32 responderEphemeralR, bytes ciphertext)",
157
148
  ]);
158
- // Smart account interface for executing calls to other contracts
159
149
  this.smartAccountInterface = new Interface([
160
150
  "function execute(address target, uint256 value, bytes calldata data) returns (bytes)",
161
151
  ]);
162
152
  }
163
153
  async sendMessage(ciphertext, topic, timestamp, nonce) {
164
- const logChainCallData = this.logChainInterface.encodeFunctionData("sendMessage", [ciphertext, topic, timestamp, nonce]);
154
+ const verbEthCallData = this.verbEthInterface.encodeFunctionData("sendMessage", [ciphertext, topic, timestamp, nonce]);
165
155
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
166
- this.logChainAddress,
167
- 0, // value
168
- logChainCallData,
156
+ this.verbEthAddress,
157
+ 0,
158
+ verbEthCallData,
169
159
  ]);
170
160
  return this.executeUserOp(smartAccountCallData);
171
161
  }
172
162
  async initiateHandshake(recipientHash, pubKeys, ephemeralPubKey, plaintextPayload) {
173
- const logChainCallData = this.logChainInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
163
+ const verbEthCallData = this.verbEthInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
174
164
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
175
- this.logChainAddress,
176
- 0, // value
177
- logChainCallData,
165
+ this.verbEthAddress,
166
+ 0,
167
+ verbEthCallData,
178
168
  ]);
179
169
  return this.executeUserOp(smartAccountCallData);
180
170
  }
181
171
  async respondToHandshake(inResponseTo, responderEphemeralR, ciphertext) {
182
- const logChainCallData = this.logChainInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
172
+ const verbEthCallData = this.verbEthInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
183
173
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
184
- this.logChainAddress,
185
- 0, // value
186
- logChainCallData,
174
+ this.verbEthAddress,
175
+ 0,
176
+ verbEthCallData,
187
177
  ]);
188
178
  return this.executeUserOp(smartAccountCallData);
189
179
  }
@@ -209,19 +199,18 @@ export class UserOpExecutor {
209
199
  return receipt;
210
200
  }
211
201
  }
212
- // Direct EntryPoint Executor - for local testing (bypasses bundler)
202
+ // Direct EntryPoint Executor (bypasses bundler for local testing)
213
203
  export class DirectEntryPointExecutor {
214
- constructor(smartAccountAddress, entryPointContract, logChainAddress, smartAccountClient, signer) {
204
+ constructor(smartAccountAddress, entryPointContract, verbEthAddress, smartAccountClient, signer) {
215
205
  this.smartAccountAddress = smartAccountAddress;
216
- this.logChainAddress = logChainAddress;
206
+ this.verbEthAddress = verbEthAddress;
217
207
  this.smartAccountClient = smartAccountClient;
218
208
  this.signer = signer;
219
- this.logChainInterface = new Interface([
209
+ this.verbEthInterface = new Interface([
220
210
  "function sendMessage(bytes calldata ciphertext, bytes32 topic, uint256 timestamp, uint256 nonce)",
221
211
  "function initiateHandshake(bytes32 recipientHash, bytes pubKeys, bytes ephemeralPubKey, bytes plaintextPayload)",
222
212
  "function respondToHandshake(bytes32 inResponseTo, bytes32 responderEphemeralR, bytes ciphertext)",
223
213
  ]);
224
- // Smart account interface for executing calls to other contracts
225
214
  this.smartAccountInterface = new Interface([
226
215
  "function execute(address target, uint256 value, bytes calldata data) returns (bytes)",
227
216
  ]);
@@ -229,29 +218,29 @@ export class DirectEntryPointExecutor {
229
218
  this.spec = detectSpecVersion(this.entryPointContract.interface);
230
219
  }
231
220
  async sendMessage(ciphertext, topic, timestamp, nonce) {
232
- const logChainCallData = this.logChainInterface.encodeFunctionData("sendMessage", [ciphertext, topic, timestamp, nonce]);
221
+ const verbEthCallData = this.verbEthInterface.encodeFunctionData("sendMessage", [ciphertext, topic, timestamp, nonce]);
233
222
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
234
- this.logChainAddress,
223
+ this.verbEthAddress,
235
224
  0, // value
236
- logChainCallData,
225
+ verbEthCallData,
237
226
  ]);
238
227
  return this.executeDirectUserOp(smartAccountCallData);
239
228
  }
240
229
  async initiateHandshake(recipientHash, pubKeys, ephemeralPubKey, plaintextPayload) {
241
- const logChainCallData = this.logChainInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
230
+ const verbEthCallData = this.verbEthInterface.encodeFunctionData("initiateHandshake", [recipientHash, pubKeys, ephemeralPubKey, plaintextPayload]);
242
231
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
243
- this.logChainAddress,
244
- 0, // value
245
- logChainCallData,
232
+ this.verbEthAddress,
233
+ 0,
234
+ verbEthCallData,
246
235
  ]);
247
236
  return this.executeDirectUserOp(smartAccountCallData);
248
237
  }
249
238
  async respondToHandshake(inResponseTo, responderEphemeralR, ciphertext) {
250
- const logChainCallData = this.logChainInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
239
+ const verbEthCallData = this.verbEthInterface.encodeFunctionData("respondToHandshake", [inResponseTo, responderEphemeralR, ciphertext]);
251
240
  const smartAccountCallData = this.smartAccountInterface.encodeFunctionData("execute", [
252
- this.logChainAddress,
253
- 0, // value
254
- logChainCallData,
241
+ this.verbEthAddress,
242
+ 0,
243
+ verbEthCallData,
255
244
  ]);
256
245
  return this.executeDirectUserOp(smartAccountCallData);
257
246
  }
@@ -290,11 +279,8 @@ export class DirectEntryPointExecutor {
290
279
  signature: "0x",
291
280
  };
292
281
  }
293
- // Pad bigints, bytes32 before signing
294
282
  const paddedUserOp = padBigints(userOp);
295
- //console.log("Padded UserOp:", paddedUserOp);
296
283
  const signed = await this.smartAccountClient.signUserOperation(paddedUserOp);
297
- // Direct submit to EntryPoint
298
284
  const tx = await this.entryPointContract.handleOps([signed], await this.signer.getAddress());
299
285
  return tx;
300
286
  }
@@ -303,33 +289,32 @@ export class ExecutorFactory {
303
289
  static createEOA(contract) {
304
290
  return new EOAExecutor(contract);
305
291
  }
306
- static createBaseSmartAccount(baseAccountProvider, logChainAddress, chainId = 8453, paymasterServiceUrl, subAccountAddress) {
307
- return new BaseSmartAccountExecutor(baseAccountProvider, logChainAddress, chainId, paymasterServiceUrl, subAccountAddress);
292
+ static createBaseSmartAccount(baseAccountProvider, verbEthAddress, chainId = 8453, paymasterServiceUrl, subAccountAddress) {
293
+ return new BaseSmartAccountExecutor(baseAccountProvider, verbEthAddress, chainId, paymasterServiceUrl, subAccountAddress);
308
294
  }
309
- static createUserOp(smartAccountAddress, _entryPointAddress, logChainAddress, bundlerClient, smartAccountClient) {
310
- return new UserOpExecutor(smartAccountAddress, logChainAddress, bundlerClient, smartAccountClient);
295
+ static createUserOp(smartAccountAddress, _entryPointAddress, verbEthAddress, bundlerClient, smartAccountClient) {
296
+ return new UserOpExecutor(smartAccountAddress, verbEthAddress, bundlerClient, smartAccountClient);
311
297
  }
312
- static createDirectEntryPoint(smartAccountAddress, entryPointContract, logChainAddress, smartAccountClient, signer) {
313
- return new DirectEntryPointExecutor(smartAccountAddress, entryPointContract, logChainAddress, smartAccountClient, signer);
298
+ static createDirectEntryPoint(smartAccountAddress, entryPointContract, verbEthAddress, smartAccountClient, signer) {
299
+ return new DirectEntryPointExecutor(smartAccountAddress, entryPointContract, verbEthAddress, smartAccountClient, signer);
314
300
  }
315
301
  // Auto-detect executor based on environment and signer type
316
302
  static async createAuto(signerOrAccount, contract, options) {
317
- if (options?.baseAccountProvider && options?.logChainAddress) {
318
- return new BaseSmartAccountExecutor(options.baseAccountProvider, options.logChainAddress, options.chainId || 8453);
303
+ if (options?.baseAccountProvider && options?.verbEthAddress) {
304
+ return new BaseSmartAccountExecutor(options.baseAccountProvider, options.verbEthAddress, options.chainId || 8453);
319
305
  }
320
306
  try {
321
307
  const provider = signerOrAccount?.provider || signerOrAccount;
322
308
  if (provider && typeof provider.request === "function") {
323
- // test if provider supports wallet_sendCalls
324
309
  const capabilities = await provider
325
310
  .request({
326
311
  method: "wallet_getCapabilities",
327
312
  params: [],
328
313
  })
329
314
  .catch(() => null);
330
- if (capabilities && options?.logChainAddress) {
315
+ if (capabilities && options?.verbEthAddress) {
331
316
  // if wallet supports capabilities, it's likely a Base Smart Account
332
- return new BaseSmartAccountExecutor(provider, options.logChainAddress, options.chainId || 8453);
317
+ return new BaseSmartAccountExecutor(provider, options.verbEthAddress, options.chainId || 8453);
333
318
  }
334
319
  }
335
320
  }
@@ -338,16 +323,15 @@ export class ExecutorFactory {
338
323
  (options?.bundlerClient || options?.entryPointContract)) {
339
324
  if (options.isTestEnvironment &&
340
325
  options.entryPointContract &&
341
- options.logChainAddress) {
342
- return new DirectEntryPointExecutor(signerOrAccount.address, options.entryPointContract, options.logChainAddress, signerOrAccount, signerOrAccount.signer || signerOrAccount);
326
+ options.verbEthAddress) {
327
+ return new DirectEntryPointExecutor(signerOrAccount.address, options.entryPointContract, options.verbEthAddress, signerOrAccount, signerOrAccount.signer || signerOrAccount);
343
328
  }
344
329
  if (options.bundlerClient &&
345
330
  options.entryPointAddress &&
346
- options.logChainAddress) {
347
- return new UserOpExecutor(signerOrAccount.address, options.logChainAddress, options.bundlerClient, signerOrAccount);
331
+ options.verbEthAddress) {
332
+ return new UserOpExecutor(signerOrAccount.address, options.verbEthAddress, options.bundlerClient, signerOrAccount);
348
333
  }
349
334
  }
350
- // default to EOA executor
351
335
  return new EOAExecutor(contract);
352
336
  }
353
337
  }
@@ -0,0 +1,51 @@
1
+ import { Signer } from "ethers";
2
+ import nacl from 'tweetnacl';
3
+ import { IdentityKeyPair, IdentityProof } from './types.js';
4
+ import { IExecutor } from './executor.js';
5
+ export interface KemKeyPair {
6
+ publicKey: Uint8Array;
7
+ secretKey: Uint8Array;
8
+ }
9
+ /**
10
+ * Initiates an on-chain handshake with unified keys and mandatory identity proof.
11
+ * Executor-agnostic: works with EOA, UserOp, and Direct EntryPoint
12
+ *
13
+ * @returns Transaction, ephemeral keypair, and KEM keypair (must be persisted for session init)
14
+ */
15
+ export declare function initiateHandshake({ executor, recipientAddress, identityKeyPair, plaintextPayload, identityProof, }: {
16
+ executor: IExecutor;
17
+ recipientAddress: string;
18
+ identityKeyPair: IdentityKeyPair;
19
+ plaintextPayload: string;
20
+ identityProof: IdentityProof;
21
+ signer?: Signer;
22
+ }): Promise<{
23
+ tx: any;
24
+ ephemeralKeyPair: nacl.BoxKeyPair;
25
+ kemKeyPair: KemKeyPair;
26
+ }>;
27
+ /**
28
+ * Responds to a handshake with unified keys and mandatory identity proof.
29
+ * Executor-agnostic: works with EOA, UserOp, and Direct EntryPoint
30
+ *
31
+ * If initiator includes KEM public key, encapsulates a shared secret and includes ciphertext in response.
32
+ *
33
+ * @returns Transaction, tag, salt, ephemeral keys, and KEM secret
34
+ */
35
+ export declare function respondToHandshake({ executor, initiatorEphemeralPubKey, responderIdentityKeyPair, note, identityProof, }: {
36
+ executor: IExecutor;
37
+ /** Initiator's ephemeral key (32 bytes X25519) OR extended key (1216 bytes: X25519 + ML-KEM) */
38
+ initiatorEphemeralPubKey: Uint8Array;
39
+ responderIdentityKeyPair: IdentityKeyPair;
40
+ note?: string;
41
+ identityProof: IdentityProof;
42
+ signer?: Signer;
43
+ }): Promise<{
44
+ tx: any;
45
+ salt: Uint8Array;
46
+ tag: `0x${string}`;
47
+ responderEphemeralSecret: Uint8Array;
48
+ responderEphemeralPublic: Uint8Array;
49
+ kemSharedSecret?: Uint8Array;
50
+ }>;
51
+ //# sourceMappingURL=handshake.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/handshake.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,MAAM,EAEP,MAAM,QAAQ,CAAC;AAChB,OAAO,IAAI,MAAM,WAAW,CAAC;AAQ7B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI1C,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,QAAQ,EACR,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,eAAe,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IACV,EAAE,EAAE,GAAG,CAAC;IACR,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAAC;IAClC,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC,CA4CD;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,QAAQ,EACR,wBAAwB,EACxB,wBAAwB,EACxB,IAAI,EACJ,aAAa,GACd,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,gGAAgG;IAChG,wBAAwB,EAAE,UAAU,CAAC;IACrC,wBAAwB,EAAE,eAAe,CAAC;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC;IACV,EAAE,EAAE,GAAG,CAAC;IACR,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,KAAK,MAAM,EAAE,CAAC;IAEnB,wBAAwB,EAAE,UAAU,CAAC;IAErC,wBAAwB,EAAE,UAAU,CAAC;IAErC,eAAe,CAAC,EAAE,UAAU,CAAC;CAC9B,CAAC,CAuFD"}
@@ -0,0 +1,105 @@
1
+ // packages/sdk/src/handshake.ts
2
+ import { keccak256, toUtf8Bytes, hexlify, getBytes } from "ethers";
3
+ import nacl from 'tweetnacl';
4
+ import { encryptStructuredPayload } from './crypto.js';
5
+ import { serializeHandshakeContent, encodeUnifiedPubKeys, createHandshakeResponseContent, } from './payload.js';
6
+ import { computeHybridTagFromResponder } from './crypto.js';
7
+ import { kem } from './pq/kem.js';
8
+ /**
9
+ * Initiates an on-chain handshake with unified keys and mandatory identity proof.
10
+ * Executor-agnostic: works with EOA, UserOp, and Direct EntryPoint
11
+ *
12
+ * @returns Transaction, ephemeral keypair, and KEM keypair (must be persisted for session init)
13
+ */
14
+ export async function initiateHandshake({ executor, recipientAddress, identityKeyPair, plaintextPayload, identityProof, }) {
15
+ if (!executor) {
16
+ throw new Error("Executor must be provided");
17
+ }
18
+ // Generate ephemeral keypair for this handshake
19
+ const ephemeralKeyPair = nacl.box.keyPair();
20
+ // Generate ML-KEM-768 keypair for PQ-hybrid key exchange
21
+ const kemKeyPair = kem.generateKeyPair();
22
+ const recipientHash = keccak256(toUtf8Bytes('contact:' + recipientAddress.toLowerCase()));
23
+ const handshakeContent = {
24
+ plaintextPayload,
25
+ identityProof
26
+ };
27
+ const serializedPayload = serializeHandshakeContent(handshakeContent);
28
+ const unifiedPubKeys = encodeUnifiedPubKeys(identityKeyPair.publicKey, identityKeyPair.signingPublicKey);
29
+ // Ephemeral public key now includes KEM public key (32 + 1184 = 1216 bytes)
30
+ const ephemeralWithKem = new Uint8Array(32 + kem.publicKeyBytes);
31
+ ephemeralWithKem.set(ephemeralKeyPair.publicKey, 0);
32
+ ephemeralWithKem.set(kemKeyPair.publicKey, 32);
33
+ const tx = await executor.initiateHandshake(recipientHash, hexlify(unifiedPubKeys), hexlify(ephemeralWithKem), toUtf8Bytes(serializedPayload));
34
+ return {
35
+ tx,
36
+ ephemeralKeyPair, // Caller must persist secretKey for ratchet session init
37
+ kemKeyPair, // Caller must also persist secretKey for KEM decapsulation
38
+ };
39
+ }
40
+ /**
41
+ * Responds to a handshake with unified keys and mandatory identity proof.
42
+ * Executor-agnostic: works with EOA, UserOp, and Direct EntryPoint
43
+ *
44
+ * If initiator includes KEM public key, encapsulates a shared secret and includes ciphertext in response.
45
+ *
46
+ * @returns Transaction, tag, salt, ephemeral keys, and KEM secret
47
+ */
48
+ export async function respondToHandshake({ executor, initiatorEphemeralPubKey, responderIdentityKeyPair, note, identityProof, }) {
49
+ if (!executor) {
50
+ throw new Error("Executor must be provided");
51
+ }
52
+ // =========================================================================
53
+ // TWO SEPARATE KEYPAIRS for unlinkability:
54
+ //
55
+ // 1. tagKeyPair (R, r): only for tag computation
56
+ // - R goes on-chain as responderEphemeralR
57
+ // - Used by Alice to verify the tag
58
+ // - not used for ratchet
59
+ //
60
+ // 2. ratchetKeyPair: For post-handshake encryption and first DH ratchet key
61
+ // - Public key goes inside encrypted payload
62
+ // - Becomes dhMySecretKey/dhMyPublicKey in ratchet session
63
+ //
64
+ // Why this matters: With a single keypair, the on-chain R would equal the
65
+ // first message's DH header, allowing observers to link HandshakeResponse
66
+ // to subsequent conversation. With two keypairs, there's no on-chain link.
67
+ // =========================================================================
68
+ const tagKeyPair = nacl.box.keyPair();
69
+ const ratchetKeyPair = nacl.box.keyPair();
70
+ // Check if initiator included KEM public key (extended format: 32 + 1184 = 1216 bytes)
71
+ const hasKem = initiatorEphemeralPubKey.length === 32 + kem.publicKeyBytes;
72
+ const initiatorX25519Pub = hasKem
73
+ ? initiatorEphemeralPubKey.slice(0, 32)
74
+ : initiatorEphemeralPubKey;
75
+ // KEM encapsulation needed for hybrid tag
76
+ let kemCiphertext;
77
+ let kemSharedSecret;
78
+ if (hasKem) {
79
+ const initiatorKemPub = initiatorEphemeralPubKey.slice(32, 32 + kem.publicKeyBytes);
80
+ const { ciphertext, sharedSecret } = kem.encapsulate(initiatorKemPub);
81
+ kemCiphertext = ciphertext;
82
+ kemSharedSecret = sharedSecret;
83
+ }
84
+ if (!kemSharedSecret) {
85
+ throw new Error("KEM is required for PQ-secure handshake");
86
+ }
87
+ // Hybrid tag combines ECDH(r, viewPubA) + kemSecret
88
+ const inResponseTo = computeHybridTagFromResponder(tagKeyPair.secretKey, initiatorX25519Pub, kemSharedSecret);
89
+ const salt = getBytes(inResponseTo);
90
+ const responseContent = createHandshakeResponseContent(responderIdentityKeyPair.publicKey, responderIdentityKeyPair.signingPublicKey, ratchetKeyPair.publicKey, // first DH ratchet key inside payload
91
+ note, identityProof, kemCiphertext);
92
+ // Encrypt using ratchetKeyPair (the epk in encrypted payload = ratchetKeyPair.publicKey)
93
+ const payload = encryptStructuredPayload(responseContent, initiatorX25519Pub, ratchetKeyPair.secretKey, ratchetKeyPair.publicKey);
94
+ // tagKeyPair.publicKey goes on-chain, not ratchetKeyPair
95
+ const tx = await executor.respondToHandshake(inResponseTo, hexlify(tagKeyPair.publicKey), toUtf8Bytes(payload));
96
+ return {
97
+ tx,
98
+ salt,
99
+ tag: inResponseTo,
100
+ // Return ratchet keys for session initialization
101
+ responderEphemeralSecret: ratchetKeyPair.secretKey,
102
+ responderEphemeralPublic: ratchetKeyPair.publicKey,
103
+ kemSharedSecret,
104
+ };
105
+ }
@@ -1,28 +1,34 @@
1
1
  import { Signer } from "ethers";
2
- import { IdentityProof } from "./types.js";
3
- interface IdentityKeyPair {
4
- publicKey: Uint8Array;
5
- secretKey: Uint8Array;
6
- signingPublicKey: Uint8Array;
7
- signingSecretKey: Uint8Array;
2
+ import { IdentityContext, IdentityKeyPair, IdentityProof } from "./types.js";
3
+ export interface DerivedIdentityKeys {
4
+ /** VerbEth identity key pair (X25519 + Ed25519) */
5
+ keyPair: IdentityKeyPair;
6
+ /** Hex-encoded secp256k1 private key for session signer */
7
+ sessionPrivateKey: string;
8
+ /** Ethereum address of the session signer */
9
+ sessionAddress: string;
10
+ /** Public key hex strings for binding message */
11
+ pkX25519Hex: string;
12
+ pkEd25519Hex: string;
13
+ }
14
+ export interface DerivedIdentityWithProof extends DerivedIdentityKeys {
15
+ identityProof: IdentityProof;
8
16
  }
9
17
  /**
10
- * HKDF (RFC 5869) identity key derivation.
11
- * Returns a proof binding the derived keypair to the wallet address.
18
+ * Derive all identity keys and session key from a single seed signature.
12
19
  */
13
- export declare function deriveIdentityKeyPairWithProof(signer: any, address: string): Promise<{
14
- keyPair: IdentityKeyPair;
15
- identityProof: {
16
- message: string;
17
- signature: string;
18
- messageRawHex?: `0x${string}`;
19
- };
20
- }>;
21
- export declare function deriveIdentityWithUnifiedKeys(signer: Signer, address: string): Promise<{
20
+ export declare function deriveIdentityKeys(signer: any, address: string): Promise<DerivedIdentityKeys>;
21
+ /**
22
+ * Create the binding proof that ties the derived keys to the Safe address.
23
+ */
24
+ export declare function createBindingProof(signer: any, address: string, derivedKeys: DerivedIdentityKeys, executorSafeAddress: string, ctx?: IdentityContext): Promise<IdentityProof>;
25
+ export declare function deriveIdentityKeyPairWithProof(signer: any, address: string, executorSafeAddress?: string, ctx?: IdentityContext): Promise<DerivedIdentityWithProof>;
26
+ export declare function deriveIdentityWithUnifiedKeys(signer: Signer, address: string, executorSafeAddress?: string, ctx?: IdentityContext): Promise<{
22
27
  identityProof: IdentityProof;
23
28
  identityPubKey: Uint8Array;
24
29
  signingPubKey: Uint8Array;
25
30
  unifiedPubKeys: Uint8Array;
31
+ sessionPrivateKey: string;
32
+ sessionAddress: string;
26
33
  }>;
27
- export {};
28
34
  //# sourceMappingURL=identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAmB,MAAM,QAAQ,CAAC;AAGjD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,UAAU,eAAe;IAEvB,SAAS,EAAE,UAAU,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;IAEtB,gBAAgB,EAAE,UAAU,CAAC;IAC7B,gBAAgB,EAAE,UAAU,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IACT,OAAO,EAAE,eAAe,CAAC;IACzB,aAAa,EAAE;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;KAC/B,CAAC;CACH,CAAC,CAyDD;AAED,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IACT,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,EAAE,UAAU,CAAC;IAC3B,aAAa,EAAE,UAAU,CAAC;IAC1B,cAAc,EAAE,UAAU,CAAC;CAC5B,CAAC,CAcD"}
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/identity.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAqC,MAAM,QAAQ,CAAC;AAGnE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAwE7E,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,OAAO,EAAE,eAAe,CAAC;IACzB,2DAA2D;IAC3D,iBAAiB,EAAE,MAAM,CAAC;IAC1B,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,aAAa,EAAE,aAAa,CAAC;CAC9B;AAMD;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC,CA8D9B;AAMD;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,mBAAmB,EAChC,mBAAmB,EAAE,MAAM,EAC3B,GAAG,CAAC,EAAE,eAAe,GACpB,OAAO,CAAC,aAAa,CAAC,CAsBxB;AAID,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,MAAM,EACf,mBAAmB,CAAC,EAAE,MAAM,EAC5B,GAAG,CAAC,EAAE,eAAe,GACpB,OAAO,CAAC,wBAAwB,CAAC,CAcnC;AAED,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,mBAAmB,CAAC,EAAE,MAAM,EAC5B,GAAG,CAAC,EAAE,eAAe,GACpB,OAAO,CAAC;IACT,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,EAAE,UAAU,CAAC;IAC3B,aAAa,EAAE,UAAU,CAAC;IAC1B,cAAc,EAAE,UAAU,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC,CAqBD"}