@hyperlane-xyz/sdk 19.7.0 → 19.9.0
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.
- package/dist/core/AltVMCoreModule.d.ts.map +1 -1
- package/dist/core/AltVMCoreModule.js +5 -6
- package/dist/core/AltVMCoreModule.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/SmartProvider/SmartProvider.d.ts +10 -3
- package/dist/providers/SmartProvider/SmartProvider.d.ts.map +1 -1
- package/dist/providers/SmartProvider/SmartProvider.js +112 -74
- package/dist/providers/SmartProvider/SmartProvider.js.map +1 -1
- package/dist/providers/SmartProvider/SmartProvider.test.d.ts +2 -0
- package/dist/providers/SmartProvider/SmartProvider.test.d.ts.map +1 -0
- package/dist/providers/SmartProvider/SmartProvider.test.js +281 -0
- package/dist/providers/SmartProvider/SmartProvider.test.js.map +1 -0
- package/dist/signers/evm/turnkey.d.ts +61 -0
- package/dist/signers/evm/turnkey.d.ts.map +1 -0
- package/dist/signers/evm/turnkey.js +190 -0
- package/dist/signers/evm/turnkey.js.map +1 -0
- package/dist/signers/svm/turnkey.d.ts +49 -0
- package/dist/signers/svm/turnkey.d.ts.map +1 -0
- package/dist/signers/svm/turnkey.js +80 -0
- package/dist/signers/svm/turnkey.js.map +1 -0
- package/dist/signers/turnkeyClient.d.ts +68 -0
- package/dist/signers/turnkeyClient.d.ts.map +1 -0
- package/dist/signers/turnkeyClient.js +104 -0
- package/dist/signers/turnkeyClient.js.map +1 -0
- package/dist/test/AltVMMockProvider.d.ts +4 -0
- package/dist/test/AltVMMockProvider.d.ts.map +1 -1
- package/dist/test/AltVMMockProvider.js +12 -0
- package/dist/test/AltVMMockProvider.js.map +1 -1
- package/dist/test/AltVMMockSigner.d.ts +3 -0
- package/dist/test/AltVMMockSigner.d.ts.map +1 -1
- package/dist/test/AltVMMockSigner.js +9 -0
- package/dist/test/AltVMMockSigner.js.map +1 -1
- package/dist/token/EvmERC20WarpRouteReader.d.ts +2 -0
- package/dist/token/EvmERC20WarpRouteReader.d.ts.map +1 -1
- package/dist/token/EvmERC20WarpRouteReader.hardhat-test.js +149 -1
- package/dist/token/EvmERC20WarpRouteReader.hardhat-test.js.map +1 -1
- package/dist/token/EvmERC20WarpRouteReader.js +101 -60
- package/dist/token/EvmERC20WarpRouteReader.js.map +1 -1
- package/dist/token/types.d.ts +1 -1
- package/dist/token/types.d.ts.map +1 -1
- package/dist/token/types.js +4 -4
- package/dist/token/types.js.map +1 -1
- package/dist/token/types.test.js +82 -0
- package/dist/token/types.test.js.map +1 -1
- package/package.json +9 -6
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { errors as EthersError, providers } from 'ethers';
|
|
3
|
+
import { AllProviderMethods } from './ProviderMethods.js';
|
|
4
|
+
import { BlockchainError, HyperlaneSmartProvider } from './SmartProvider.js';
|
|
5
|
+
import { ProviderStatus } from './types.js';
|
|
6
|
+
// Dummy provider for testing
|
|
7
|
+
class MockProvider extends providers.BaseProvider {
|
|
8
|
+
baseUrl;
|
|
9
|
+
errorToThrow;
|
|
10
|
+
successValue;
|
|
11
|
+
responseDelayMs;
|
|
12
|
+
supportedMethods = AllProviderMethods;
|
|
13
|
+
called = false;
|
|
14
|
+
thrownError;
|
|
15
|
+
static success(successValue, responseDelayMs = 0) {
|
|
16
|
+
return new MockProvider('http://provider', undefined, successValue, responseDelayMs);
|
|
17
|
+
}
|
|
18
|
+
static error(errorToThrow, responseDelayMs = 0) {
|
|
19
|
+
return new MockProvider('http://provider', errorToThrow, undefined, responseDelayMs);
|
|
20
|
+
}
|
|
21
|
+
constructor(baseUrl, errorToThrow, successValue, responseDelayMs = 0) {
|
|
22
|
+
super({ name: 'test', chainId: 1 });
|
|
23
|
+
this.baseUrl = baseUrl;
|
|
24
|
+
this.errorToThrow = errorToThrow;
|
|
25
|
+
this.successValue = successValue;
|
|
26
|
+
this.responseDelayMs = responseDelayMs;
|
|
27
|
+
}
|
|
28
|
+
getBaseUrl() {
|
|
29
|
+
return this.baseUrl;
|
|
30
|
+
}
|
|
31
|
+
async perform(_method, _params, _reqId) {
|
|
32
|
+
this.called = true;
|
|
33
|
+
if (this.responseDelayMs > 0) {
|
|
34
|
+
await new Promise((resolve) => setTimeout(resolve, this.responseDelayMs));
|
|
35
|
+
}
|
|
36
|
+
if (this.errorToThrow) {
|
|
37
|
+
this.thrownError = this.errorToThrow;
|
|
38
|
+
throw this.errorToThrow;
|
|
39
|
+
}
|
|
40
|
+
return this.successValue ?? 'success';
|
|
41
|
+
}
|
|
42
|
+
// Required BaseProvider methods - minimal implementations
|
|
43
|
+
async detectNetwork() {
|
|
44
|
+
return { name: 'test', chainId: 1 };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
class TestableSmartProvider extends HyperlaneSmartProvider {
|
|
48
|
+
mockProviders;
|
|
49
|
+
constructor(mockProviders) {
|
|
50
|
+
super({ chainId: 1, name: 'test' }, mockProviders.map((p) => ({ http: p.getBaseUrl() })), [], { fallbackStaggerMs: 50 });
|
|
51
|
+
this.mockProviders = mockProviders;
|
|
52
|
+
}
|
|
53
|
+
testGetCombinedProviderError(errors, fallbackMsg) {
|
|
54
|
+
return this.getCombinedProviderError(errors, fallbackMsg);
|
|
55
|
+
}
|
|
56
|
+
async simplePerform(method, reqId) {
|
|
57
|
+
return this.performWithFallback(method, {}, this.mockProviders, reqId);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
class ProviderError extends Error {
|
|
61
|
+
reason;
|
|
62
|
+
code;
|
|
63
|
+
constructor(message, code) {
|
|
64
|
+
super(message);
|
|
65
|
+
this.reason = message;
|
|
66
|
+
this.code = code;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
describe('SmartProvider', () => {
|
|
70
|
+
let provider;
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
provider = new TestableSmartProvider([MockProvider.success('success')]);
|
|
73
|
+
});
|
|
74
|
+
describe('getCombinedProviderError', () => {
|
|
75
|
+
const blockchainErrorTestCases = [
|
|
76
|
+
{
|
|
77
|
+
code: EthersError.INSUFFICIENT_FUNDS,
|
|
78
|
+
message: 'insufficient funds for intrinsic transaction cost',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
code: EthersError.UNPREDICTABLE_GAS_LIMIT,
|
|
82
|
+
message: 'execution reverted: ERC20: transfer to the zero address',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
code: EthersError.CALL_EXCEPTION,
|
|
86
|
+
message: 'execution reverted',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
code: EthersError.NONCE_EXPIRED,
|
|
90
|
+
message: 'nonce has already been used',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
code: EthersError.REPLACEMENT_UNDERPRICED,
|
|
94
|
+
message: 'replacement transaction underpriced',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
code: EthersError.TRANSACTION_REPLACED,
|
|
98
|
+
message: 'transaction was replaced',
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
blockchainErrorTestCases.forEach(({ code, message }) => {
|
|
102
|
+
it(`throws BlockchainError with isRecoverable=false for ${code}`, () => {
|
|
103
|
+
const error = new ProviderError(message, code);
|
|
104
|
+
const CombinedError = provider.testGetCombinedProviderError([error], 'Test fallback message');
|
|
105
|
+
const e = new CombinedError();
|
|
106
|
+
expect(e).to.be.instanceOf(BlockchainError);
|
|
107
|
+
expect(e.isRecoverable).to.equal(false);
|
|
108
|
+
expect(e.message).to.equal(message);
|
|
109
|
+
expect(e.cause).to.equal(error);
|
|
110
|
+
expect(e.cause.code).to.equal(code);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
it('throws regular Error for SERVER_ERROR (not BlockchainError)', () => {
|
|
114
|
+
const error = new ProviderError('connection refused', EthersError.SERVER_ERROR);
|
|
115
|
+
const CombinedError = provider.testGetCombinedProviderError([error], 'Test fallback message');
|
|
116
|
+
const e = new CombinedError();
|
|
117
|
+
expect(e).to.be.instanceOf(Error);
|
|
118
|
+
expect(e).to.not.be.instanceOf(BlockchainError);
|
|
119
|
+
expect(e.isRecoverable).to.be.undefined;
|
|
120
|
+
expect(e.cause).to.equal(error);
|
|
121
|
+
expect(e.cause.code).to.equal(EthersError.SERVER_ERROR);
|
|
122
|
+
});
|
|
123
|
+
it('throws regular Error for TIMEOUT (not BlockchainError)', () => {
|
|
124
|
+
const error = { status: ProviderStatus.Timeout };
|
|
125
|
+
const CombinedError = provider.testGetCombinedProviderError([error], 'Test fallback message');
|
|
126
|
+
const e = new CombinedError();
|
|
127
|
+
expect(e).to.be.instanceOf(Error);
|
|
128
|
+
expect(e).to.not.be.instanceOf(BlockchainError);
|
|
129
|
+
expect(e.isRecoverable).to.be.undefined;
|
|
130
|
+
expect(e.cause).to.equal(error);
|
|
131
|
+
});
|
|
132
|
+
const mixedErrorTestCases = [
|
|
133
|
+
{
|
|
134
|
+
name: 'SERVER_ERROR',
|
|
135
|
+
errors: () => [
|
|
136
|
+
new ProviderError('connection refused', EthersError.SERVER_ERROR),
|
|
137
|
+
new ProviderError('execution reverted', EthersError.CALL_EXCEPTION),
|
|
138
|
+
],
|
|
139
|
+
expectedMessage: 'execution reverted',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'TIMEOUT',
|
|
143
|
+
errors: () => [
|
|
144
|
+
{ status: ProviderStatus.Timeout },
|
|
145
|
+
new ProviderError('insufficient funds', EthersError.INSUFFICIENT_FUNDS),
|
|
146
|
+
],
|
|
147
|
+
expectedMessage: 'insufficient funds',
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
mixedErrorTestCases.forEach(({ name, errors, expectedMessage }) => {
|
|
151
|
+
it(`prioritizes BlockchainError when mixed with ${name}`, () => {
|
|
152
|
+
const [firstError, secondError] = errors();
|
|
153
|
+
const CombinedError = provider.testGetCombinedProviderError([firstError, secondError], 'Test fallback message');
|
|
154
|
+
const e = new CombinedError();
|
|
155
|
+
expect(e).to.be.instanceOf(BlockchainError);
|
|
156
|
+
expect(e.isRecoverable).to.equal(false);
|
|
157
|
+
expect(e.message).to.equal(expectedMessage);
|
|
158
|
+
expect(e.cause).to.equal(secondError);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe('performWithFallback', () => {
|
|
163
|
+
it('returns success from first provider, second provider not called', async () => {
|
|
164
|
+
const provider1 = MockProvider.success('success1');
|
|
165
|
+
const provider2 = MockProvider.success('success2');
|
|
166
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
167
|
+
const result = await provider.simplePerform('getBlockNumber', 1);
|
|
168
|
+
expect(result).to.deep.equal('success1');
|
|
169
|
+
expect(provider1.called).to.be.true;
|
|
170
|
+
expect(provider2.called).to.be.false;
|
|
171
|
+
});
|
|
172
|
+
it('calls second provider when first throws server error, returns success from second', async () => {
|
|
173
|
+
const serverError = new ProviderError('connection refused', EthersError.SERVER_ERROR);
|
|
174
|
+
const provider1 = MockProvider.error(serverError);
|
|
175
|
+
const provider2 = MockProvider.success('success2');
|
|
176
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
177
|
+
const result = await provider.simplePerform('getBlockNumber', 1);
|
|
178
|
+
expect(result).to.deep.equal('success2');
|
|
179
|
+
expect(provider1.called).to.be.true;
|
|
180
|
+
expect(provider1.thrownError).to.equal(serverError);
|
|
181
|
+
expect(provider2.called).to.be.true;
|
|
182
|
+
});
|
|
183
|
+
it('calls second provider when first times out, returns success from second', async () => {
|
|
184
|
+
const provider1 = MockProvider.success('success1', 100);
|
|
185
|
+
const provider2 = MockProvider.success('success2');
|
|
186
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
187
|
+
const result = await provider.simplePerform('getBlockNumber', 1);
|
|
188
|
+
expect(result).to.deep.equal('success2');
|
|
189
|
+
expect(provider1.called).to.be.true;
|
|
190
|
+
expect(provider2.called).to.be.true;
|
|
191
|
+
});
|
|
192
|
+
it('both providers timeout, first provider ultimately returns result (waitForProviderSuccess)', async () => {
|
|
193
|
+
const provider1 = MockProvider.success('success1', 120); // 120ms delay
|
|
194
|
+
const provider2 = MockProvider.success('success2', 200); // 200ms delay
|
|
195
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
196
|
+
const result = await provider.simplePerform('getBlockNumber', 1);
|
|
197
|
+
expect(result).to.deep.equal('success1');
|
|
198
|
+
expect(provider1.called).to.be.true;
|
|
199
|
+
expect(provider2.called).to.be.true;
|
|
200
|
+
});
|
|
201
|
+
it('both providers throw errors, combined error is thrown', async () => {
|
|
202
|
+
const serverError1 = new ProviderError('connection refused 1', EthersError.SERVER_ERROR);
|
|
203
|
+
const serverError2 = new ProviderError('connection refused 2', EthersError.SERVER_ERROR);
|
|
204
|
+
const provider1 = MockProvider.error(serverError1);
|
|
205
|
+
const provider2 = MockProvider.error(serverError2);
|
|
206
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
207
|
+
try {
|
|
208
|
+
await provider.simplePerform('getBlockNumber', 1);
|
|
209
|
+
expect.fail('Should have thrown an error');
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
expect(e).to.be.instanceOf(Error);
|
|
213
|
+
expect(e).to.not.be.instanceOf(BlockchainError);
|
|
214
|
+
expect(e.isRecoverable).to.be.undefined;
|
|
215
|
+
expect(e.cause).to.equal(serverError1); // First error should be the cause
|
|
216
|
+
expect(provider1.called).to.be.true;
|
|
217
|
+
expect(provider1.thrownError).to.equal(serverError1);
|
|
218
|
+
expect(provider2.called).to.be.true;
|
|
219
|
+
expect(provider2.thrownError).to.equal(serverError2);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
it('both providers timeout, combined timeout error is thrown', async () => {
|
|
223
|
+
const provider1 = MockProvider.success('success1', 2000);
|
|
224
|
+
const provider2 = MockProvider.success('success2', 2000);
|
|
225
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
226
|
+
try {
|
|
227
|
+
await provider.simplePerform('getBlockNumber', 1);
|
|
228
|
+
expect.fail('Should have thrown an error');
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
expect(e).to.be.instanceOf(Error);
|
|
232
|
+
expect(e).to.not.be.instanceOf(BlockchainError);
|
|
233
|
+
expect(e.isRecoverable).to.be.undefined;
|
|
234
|
+
expect(e.message).to.include('All providers timed out');
|
|
235
|
+
expect(provider1.called).to.be.true;
|
|
236
|
+
expect(provider2.called).to.be.true;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
it('blockchain error stops trying additional providers immediately', async () => {
|
|
240
|
+
const blockchainError = new ProviderError('execution reverted', EthersError.CALL_EXCEPTION);
|
|
241
|
+
const provider1 = MockProvider.error(blockchainError);
|
|
242
|
+
const provider2 = MockProvider.success('success2');
|
|
243
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
244
|
+
try {
|
|
245
|
+
await provider.simplePerform('getBlockNumber', 1);
|
|
246
|
+
expect.fail('Should have thrown an error');
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
expect(e).to.be.instanceOf(BlockchainError);
|
|
250
|
+
expect(e.isRecoverable).to.equal(false);
|
|
251
|
+
expect(e.message).to.equal('execution reverted');
|
|
252
|
+
expect(e.cause).to.equal(blockchainError);
|
|
253
|
+
expect(provider1.called).to.be.true;
|
|
254
|
+
expect(provider1.thrownError).to.equal(blockchainError);
|
|
255
|
+
expect(provider2.called).to.be.false; // Key test - second provider should NOT be called
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
it('blockchain error takes priority over server error in actual flow', async () => {
|
|
259
|
+
const serverError = new ProviderError('connection refused', EthersError.SERVER_ERROR);
|
|
260
|
+
const blockchainError = new ProviderError('insufficient funds', EthersError.INSUFFICIENT_FUNDS);
|
|
261
|
+
const provider1 = MockProvider.error(serverError);
|
|
262
|
+
const provider2 = MockProvider.error(blockchainError);
|
|
263
|
+
const provider = new TestableSmartProvider([provider1, provider2]);
|
|
264
|
+
try {
|
|
265
|
+
await provider.simplePerform('getBlockNumber', 1);
|
|
266
|
+
expect.fail('Should have thrown an error');
|
|
267
|
+
}
|
|
268
|
+
catch (e) {
|
|
269
|
+
expect(e).to.be.instanceOf(BlockchainError); // Should get blockchain error, not server error
|
|
270
|
+
expect(e.isRecoverable).to.equal(false);
|
|
271
|
+
expect(e.message).to.equal('insufficient funds');
|
|
272
|
+
expect(e.cause).to.equal(blockchainError);
|
|
273
|
+
expect(provider1.called).to.be.true;
|
|
274
|
+
expect(provider1.thrownError).to.equal(serverError);
|
|
275
|
+
expect(provider2.called).to.be.true;
|
|
276
|
+
expect(provider2.thrownError).to.equal(blockchainError);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
//# sourceMappingURL=SmartProvider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SmartProvider.test.js","sourceRoot":"","sources":["../../../src/providers/SmartProvider/SmartProvider.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { TurnkeyConfig } from '../turnkeyClient.js';
|
|
3
|
+
/**
|
|
4
|
+
* Turnkey signer for EVM transactions
|
|
5
|
+
* Uses Turnkey's secure enclaves to sign transactions without exposing private keys
|
|
6
|
+
* This is a custom ethers v5-compatible Signer that uses Turnkey SDK directly
|
|
7
|
+
* Uses composition to access Turnkey functionality while extending ethers.Signer
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const config: TurnkeyConfig = {
|
|
12
|
+
* organizationId: 'your-org-id',
|
|
13
|
+
* apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY,
|
|
14
|
+
* apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY,
|
|
15
|
+
* privateKeyId: 'your-private-key-id',
|
|
16
|
+
* publicKey: '0x...', // Ethereum address
|
|
17
|
+
* };
|
|
18
|
+
*
|
|
19
|
+
* const provider = new ethers.providers.JsonRpcProvider('...');
|
|
20
|
+
* const signer = new TurnkeyEvmSigner(config, provider);
|
|
21
|
+
*
|
|
22
|
+
* // Use with MultiProvider
|
|
23
|
+
* multiProvider.setSigner('ethereum', signer);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class TurnkeyEvmSigner extends ethers.Signer {
|
|
27
|
+
private readonly manager;
|
|
28
|
+
readonly address: string;
|
|
29
|
+
readonly provider: ethers.providers.Provider | undefined;
|
|
30
|
+
constructor(config: TurnkeyConfig, provider?: ethers.providers.Provider);
|
|
31
|
+
/**
|
|
32
|
+
* Health check - delegates to manager
|
|
33
|
+
*/
|
|
34
|
+
healthCheck(): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Get an ethers Signer connected to the provided provider
|
|
37
|
+
* This returns a new instance with the provider connected
|
|
38
|
+
*/
|
|
39
|
+
getSigner(provider: ethers.providers.Provider): Promise<ethers.Signer>;
|
|
40
|
+
/**
|
|
41
|
+
* Connect this signer to a provider (creates new instance with proper configuration)
|
|
42
|
+
*/
|
|
43
|
+
connect(provider: ethers.providers.Provider): TurnkeyEvmSigner;
|
|
44
|
+
/**
|
|
45
|
+
* Get the address of this signer
|
|
46
|
+
*/
|
|
47
|
+
getAddress(): Promise<string>;
|
|
48
|
+
/**
|
|
49
|
+
* Sign a transaction using Turnkey
|
|
50
|
+
*/
|
|
51
|
+
signTransaction(transaction: ethers.providers.TransactionRequest): Promise<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Sign a message using Turnkey
|
|
54
|
+
*/
|
|
55
|
+
signMessage(message: string | ethers.utils.Bytes): Promise<string>;
|
|
56
|
+
/**
|
|
57
|
+
* Populate a transaction with default values (nonce, gas, etc.)
|
|
58
|
+
*/
|
|
59
|
+
populateTransaction(transaction: ethers.providers.TransactionRequest): Promise<ethers.providers.TransactionRequest>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=turnkey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turnkey.d.ts","sourceRoot":"","sources":["../../../src/signers/evm/turnkey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,OAAO,EAEL,aAAa,EAGd,MAAM,qBAAqB,CAAC;AAI7B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,gBAAiB,SAAQ,MAAM,CAAC,MAAM;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,SAAgB,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC;gBAEpD,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,QAAQ;IASvE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;OAGG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;IAK5E;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,QAAQ,GAAG,gBAAgB;IAI9D;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAInC;;OAEG;IACG,eAAe,CACnB,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAC/C,OAAO,CAAC,MAAM,CAAC;IA0DlB;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IA6CxE;;OAEG;IACG,mBAAmB,CACvB,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,kBAAkB,GAC/C,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,kBAAkB,CAAC;CA4ChD"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
import { rootLogger } from '@hyperlane-xyz/utils';
|
|
3
|
+
import { TurnkeyClientManager, logTurnkeyError, validateTurnkeyActivityCompleted, } from '../turnkeyClient.js';
|
|
4
|
+
const logger = rootLogger.child({ module: 'sdk:turnkey-evm' });
|
|
5
|
+
/**
|
|
6
|
+
* Turnkey signer for EVM transactions
|
|
7
|
+
* Uses Turnkey's secure enclaves to sign transactions without exposing private keys
|
|
8
|
+
* This is a custom ethers v5-compatible Signer that uses Turnkey SDK directly
|
|
9
|
+
* Uses composition to access Turnkey functionality while extending ethers.Signer
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const config: TurnkeyConfig = {
|
|
14
|
+
* organizationId: 'your-org-id',
|
|
15
|
+
* apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY,
|
|
16
|
+
* apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY,
|
|
17
|
+
* privateKeyId: 'your-private-key-id',
|
|
18
|
+
* publicKey: '0x...', // Ethereum address
|
|
19
|
+
* };
|
|
20
|
+
*
|
|
21
|
+
* const provider = new ethers.providers.JsonRpcProvider('...');
|
|
22
|
+
* const signer = new TurnkeyEvmSigner(config, provider);
|
|
23
|
+
*
|
|
24
|
+
* // Use with MultiProvider
|
|
25
|
+
* multiProvider.setSigner('ethereum', signer);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class TurnkeyEvmSigner extends ethers.Signer {
|
|
29
|
+
manager;
|
|
30
|
+
address;
|
|
31
|
+
provider;
|
|
32
|
+
constructor(config, provider) {
|
|
33
|
+
super();
|
|
34
|
+
this.manager = new TurnkeyClientManager(config);
|
|
35
|
+
this.address = config.publicKey;
|
|
36
|
+
this.provider = provider;
|
|
37
|
+
logger.debug(`Initialized Turnkey EVM signer for key: ${this.address}`);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Health check - delegates to manager
|
|
41
|
+
*/
|
|
42
|
+
async healthCheck() {
|
|
43
|
+
return this.manager.healthCheck();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get an ethers Signer connected to the provided provider
|
|
47
|
+
* This returns a new instance with the provider connected
|
|
48
|
+
*/
|
|
49
|
+
async getSigner(provider) {
|
|
50
|
+
logger.debug('Creating Turnkey EVM signer for transaction');
|
|
51
|
+
return this.connect(provider);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Connect this signer to a provider (creates new instance with proper configuration)
|
|
55
|
+
*/
|
|
56
|
+
connect(provider) {
|
|
57
|
+
return new TurnkeyEvmSigner(this.manager.getConfig(), provider);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get the address of this signer
|
|
61
|
+
*/
|
|
62
|
+
async getAddress() {
|
|
63
|
+
return this.address;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Sign a transaction using Turnkey
|
|
67
|
+
*/
|
|
68
|
+
async signTransaction(transaction) {
|
|
69
|
+
if (!this.provider) {
|
|
70
|
+
throw new Error('Provider required to sign transaction');
|
|
71
|
+
}
|
|
72
|
+
logger.debug('Signing transaction with Turnkey', {
|
|
73
|
+
to: transaction.to,
|
|
74
|
+
value: transaction.value?.toString(),
|
|
75
|
+
});
|
|
76
|
+
try {
|
|
77
|
+
// Populate the transaction (fill in nonce, gasPrice, etc.)
|
|
78
|
+
const populatedTx = await ethers.utils.resolveProperties(await this.populateTransaction(transaction));
|
|
79
|
+
// Remove 'from' field for serialization
|
|
80
|
+
const { from: _, ...txToSerialize } = populatedTx;
|
|
81
|
+
// For EIP-1559 transactions, explicitly set type: 2 and remove gasPrice
|
|
82
|
+
if (txToSerialize.maxFeePerGas || txToSerialize.maxPriorityFeePerGas) {
|
|
83
|
+
txToSerialize.type = 2;
|
|
84
|
+
delete txToSerialize.gasPrice;
|
|
85
|
+
}
|
|
86
|
+
const unsignedTx = ethers.utils.serializeTransaction(txToSerialize);
|
|
87
|
+
// Remove 0x prefix for Turnkey API (it expects raw hex)
|
|
88
|
+
const unsignedTxHex = unsignedTx.startsWith('0x')
|
|
89
|
+
? unsignedTx.slice(2)
|
|
90
|
+
: unsignedTx;
|
|
91
|
+
// Sign using Turnkey's signTransaction API
|
|
92
|
+
const { activity } = await this.manager.getClient().signTransaction({
|
|
93
|
+
signWith: this.address,
|
|
94
|
+
type: 'TRANSACTION_TYPE_ETHEREUM',
|
|
95
|
+
unsignedTransaction: unsignedTxHex,
|
|
96
|
+
});
|
|
97
|
+
validateTurnkeyActivityCompleted(activity, 'Transaction signing');
|
|
98
|
+
const signedTx = activity.result?.signTransactionResult?.signedTransaction;
|
|
99
|
+
if (!signedTx) {
|
|
100
|
+
throw new Error('No signed transaction returned from Turnkey');
|
|
101
|
+
}
|
|
102
|
+
logger.debug('Transaction signed successfully');
|
|
103
|
+
// Ensure the signed transaction has 0x prefix
|
|
104
|
+
return signedTx.startsWith('0x') ? signedTx : `0x${signedTx}`;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
logTurnkeyError('Failed to sign transaction with Turnkey', error);
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Sign a message using Turnkey
|
|
113
|
+
*/
|
|
114
|
+
async signMessage(message) {
|
|
115
|
+
logger.debug('Signing message with Turnkey');
|
|
116
|
+
try {
|
|
117
|
+
const messageBytes = typeof message === 'string'
|
|
118
|
+
? ethers.utils.toUtf8Bytes(message)
|
|
119
|
+
: message;
|
|
120
|
+
const messageHash = ethers.utils.hashMessage(messageBytes);
|
|
121
|
+
// Sign raw payload using Turnkey
|
|
122
|
+
const { activity, r, s, v } = await this.manager
|
|
123
|
+
.getClient()
|
|
124
|
+
.signRawPayload({
|
|
125
|
+
signWith: this.address,
|
|
126
|
+
payload: messageHash.slice(2), // Remove 0x prefix
|
|
127
|
+
encoding: 'PAYLOAD_ENCODING_HEXADECIMAL',
|
|
128
|
+
hashFunction: 'HASH_FUNCTION_NO_OP',
|
|
129
|
+
});
|
|
130
|
+
validateTurnkeyActivityCompleted(activity, 'Message signing');
|
|
131
|
+
// Validate signature components
|
|
132
|
+
if (!r || !s || !v) {
|
|
133
|
+
throw new Error('Missing signature components from Turnkey');
|
|
134
|
+
}
|
|
135
|
+
const hexPattern = /^0x[0-9a-fA-F]+$/;
|
|
136
|
+
if (!hexPattern.test(r) || !hexPattern.test(s)) {
|
|
137
|
+
throw new Error('Invalid signature format from Turnkey');
|
|
138
|
+
}
|
|
139
|
+
const vNum = parseInt(v, 16);
|
|
140
|
+
if (isNaN(vNum)) {
|
|
141
|
+
throw new Error(`Invalid v value from Turnkey: ${v}`);
|
|
142
|
+
}
|
|
143
|
+
// Reconstruct the signature from r, s, v
|
|
144
|
+
return ethers.utils.joinSignature({ r, s, v: vNum });
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
logTurnkeyError('Failed to sign message with Turnkey', error);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Populate a transaction with default values (nonce, gas, etc.)
|
|
153
|
+
*/
|
|
154
|
+
async populateTransaction(transaction) {
|
|
155
|
+
if (!this.provider) {
|
|
156
|
+
throw new Error('Provider required to populate transaction');
|
|
157
|
+
}
|
|
158
|
+
const tx = { ...transaction };
|
|
159
|
+
// Set from address
|
|
160
|
+
if (!tx.from) {
|
|
161
|
+
tx.from = this.address;
|
|
162
|
+
}
|
|
163
|
+
// Get nonce if not set
|
|
164
|
+
if (tx.nonce == null) {
|
|
165
|
+
tx.nonce = await this.provider.getTransactionCount(this.address, 'pending');
|
|
166
|
+
}
|
|
167
|
+
// Get gas price if not set
|
|
168
|
+
if (tx.gasPrice == null && tx.maxFeePerGas == null) {
|
|
169
|
+
const feeData = await this.provider.getFeeData();
|
|
170
|
+
if (feeData.maxFeePerGas) {
|
|
171
|
+
tx.maxFeePerGas = feeData.maxFeePerGas;
|
|
172
|
+
tx.maxPriorityFeePerGas = feeData.maxPriorityFeePerGas || undefined;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
tx.gasPrice = feeData.gasPrice || undefined;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Get chain ID if not set
|
|
179
|
+
if (tx.chainId == null) {
|
|
180
|
+
const network = await this.provider.getNetwork();
|
|
181
|
+
tx.chainId = network.chainId;
|
|
182
|
+
}
|
|
183
|
+
// Estimate gas if not set
|
|
184
|
+
if (tx.gasLimit == null) {
|
|
185
|
+
tx.gasLimit = await this.provider.estimateGas(tx);
|
|
186
|
+
}
|
|
187
|
+
return tx;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=turnkey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turnkey.js","sourceRoot":"","sources":["../../../src/signers/evm/turnkey.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { PublicKey, Transaction } from '@solana/web3.js';
|
|
2
|
+
import { TurnkeyConfig } from '../turnkeyClient.js';
|
|
3
|
+
import { SvmTransactionSigner } from './solana-web3js.js';
|
|
4
|
+
/**
|
|
5
|
+
* Turnkey signer for Solana/SVM transactions
|
|
6
|
+
* Provides a Keypair-like interface but signs transactions using Turnkey's secure enclaves
|
|
7
|
+
* Uses composition to access Turnkey functionality while implementing SVM interface
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const config: TurnkeyConfig = {
|
|
12
|
+
* organizationId: 'your-org-id',
|
|
13
|
+
* apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY,
|
|
14
|
+
* apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY,
|
|
15
|
+
* privateKeyId: 'your-private-key-id',
|
|
16
|
+
* publicKey: 'base58-solana-pubkey',
|
|
17
|
+
* };
|
|
18
|
+
*
|
|
19
|
+
* const signer = new TurnkeySealevelSigner(config);
|
|
20
|
+
*
|
|
21
|
+
* // Use with SvmMultiProtocolSignerAdapter
|
|
22
|
+
* const adapter = new SvmMultiProtocolSignerAdapter(
|
|
23
|
+
* 'solana',
|
|
24
|
+
* signer,
|
|
25
|
+
* multiProtocolProvider
|
|
26
|
+
* );
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare class TurnkeySealevelSigner implements SvmTransactionSigner {
|
|
30
|
+
private readonly manager;
|
|
31
|
+
private readonly turnkeySigner;
|
|
32
|
+
readonly publicKey: PublicKey;
|
|
33
|
+
constructor(config: TurnkeyConfig);
|
|
34
|
+
/**
|
|
35
|
+
* Health check - delegates to manager
|
|
36
|
+
*/
|
|
37
|
+
healthCheck(): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Get a signer (returns this instance)
|
|
40
|
+
*/
|
|
41
|
+
getSigner(): Promise<this>;
|
|
42
|
+
/**
|
|
43
|
+
* Sign a Solana transaction using Turnkey
|
|
44
|
+
* This method uses Turnkey's secure enclave to sign the transaction
|
|
45
|
+
* and enforces any policies configured in Turnkey (e.g., IGP-only restrictions)
|
|
46
|
+
*/
|
|
47
|
+
signTransaction(transaction: Transaction): Promise<Transaction>;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=turnkey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turnkey.d.ts","sourceRoot":"","sources":["../../../src/signers/svm/turnkey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKzD,OAAO,EAEL,aAAa,EAEd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAI1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,qBAAsB,YAAW,oBAAoB;IAChE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,SAAgB,SAAS,EAAE,SAAS,CAAC;gBAEzB,MAAM,EAAE,aAAa;IAejC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;OAIG;IACG,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;CAsBtE"}
|