@dfns/lib-ethersjs5 0.1.0-beta.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.
- package/index.d.ts +20 -0
- package/index.js +113 -0
- package/package.json +22 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DfnsApiClient } from '@dfns/sdk';
|
|
2
|
+
import { Provider, TransactionRequest } from '@ethersproject/abstract-provider';
|
|
3
|
+
import { Signer, TypedDataDomain, TypedDataField, TypedDataSigner } from '@ethersproject/abstract-signer';
|
|
4
|
+
export type DfnsWalletOptions = {
|
|
5
|
+
walletId: string;
|
|
6
|
+
dfnsClient: DfnsApiClient;
|
|
7
|
+
maxRetries?: number;
|
|
8
|
+
retryInterval?: number;
|
|
9
|
+
};
|
|
10
|
+
export declare class DfnsWallet extends Signer implements TypedDataSigner {
|
|
11
|
+
private address?;
|
|
12
|
+
private options;
|
|
13
|
+
constructor(options: DfnsWalletOptions, provider?: Provider | null);
|
|
14
|
+
connect(provider: Provider | null): Signer;
|
|
15
|
+
getAddress(): Promise<string>;
|
|
16
|
+
waitForSignature(signatureId: string): Promise<string>;
|
|
17
|
+
signTransaction(transaction: TransactionRequest): Promise<string>;
|
|
18
|
+
signMessage(message: string | Uint8Array): Promise<string>;
|
|
19
|
+
_signTypedData(domain: TypedDataDomain, types: Record<string, TypedDataField[]>, value: Record<string, any>): Promise<string>;
|
|
20
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DfnsWallet = void 0;
|
|
4
|
+
const Wallets_1 = require("@dfns/sdk/codegen/datamodel/Wallets");
|
|
5
|
+
const address_1 = require("@ethersproject/address");
|
|
6
|
+
const abstract_signer_1 = require("@ethersproject/abstract-signer");
|
|
7
|
+
const bytes_1 = require("@ethersproject/bytes");
|
|
8
|
+
const hash_1 = require("@ethersproject/hash");
|
|
9
|
+
const keccak256_1 = require("@ethersproject/keccak256");
|
|
10
|
+
const properties_1 = require("@ethersproject/properties");
|
|
11
|
+
const transactions_1 = require("@ethersproject/transactions");
|
|
12
|
+
const sleep = (interval = 0) => new Promise((resolve) => setTimeout(resolve, interval));
|
|
13
|
+
class DfnsWallet extends abstract_signer_1.Signer {
|
|
14
|
+
constructor(options, provider) {
|
|
15
|
+
var _a, _b;
|
|
16
|
+
super();
|
|
17
|
+
this.options = {
|
|
18
|
+
...options,
|
|
19
|
+
maxRetries: (_a = options.maxRetries) !== null && _a !== void 0 ? _a : 3,
|
|
20
|
+
retryInterval: (_b = options.retryInterval) !== null && _b !== void 0 ? _b : 1000,
|
|
21
|
+
};
|
|
22
|
+
(0, properties_1.defineReadOnly)(this, 'provider', provider || undefined);
|
|
23
|
+
}
|
|
24
|
+
connect(provider) {
|
|
25
|
+
return new DfnsWallet(this.options, provider);
|
|
26
|
+
}
|
|
27
|
+
async getAddress() {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
if (!this.address) {
|
|
30
|
+
const { walletId, dfnsClient } = this.options;
|
|
31
|
+
const res = await dfnsClient.wallets.getWallet({ walletId });
|
|
32
|
+
if (!res.signingKey || res.signingKey.scheme !== Wallets_1.KeyScheme.ECDSA || res.signingKey.curve !== Wallets_1.KeyCurve.secp256k1) {
|
|
33
|
+
throw new Error(`wallet ${walletId} has incompatible scheme (${(_a = res.signingKey) === null || _a === void 0 ? void 0 : _a.scheme}) or curve (${(_b = res.signingKey) === null || _b === void 0 ? void 0 : _b.curve})`);
|
|
34
|
+
}
|
|
35
|
+
if (res.address) {
|
|
36
|
+
this.address = (0, address_1.getAddress)(res.address);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.address = (0, transactions_1.computeAddress)('0x' + res.signingKey.publicKey);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return this.address;
|
|
43
|
+
}
|
|
44
|
+
async waitForSignature(signatureId) {
|
|
45
|
+
const { walletId, dfnsClient, retryInterval } = this.options;
|
|
46
|
+
let maxRetries = this.options.maxRetries;
|
|
47
|
+
while (maxRetries > 0) {
|
|
48
|
+
await sleep(retryInterval);
|
|
49
|
+
const res = await dfnsClient.wallets.getSignature({ walletId, signatureId });
|
|
50
|
+
if (res.status === Wallets_1.SignatureStatus.Signed) {
|
|
51
|
+
if (!res.signature)
|
|
52
|
+
break;
|
|
53
|
+
return (0, bytes_1.joinSignature)({
|
|
54
|
+
r: res.signature.r,
|
|
55
|
+
s: res.signature.s,
|
|
56
|
+
recoveryParam: res.signature.recid,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
else if (res.status === Wallets_1.SignatureStatus.Failed) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
maxRetries -= 1;
|
|
63
|
+
}
|
|
64
|
+
throw new Error(`signature ${signatureId} not available`);
|
|
65
|
+
}
|
|
66
|
+
async signTransaction(transaction) {
|
|
67
|
+
return (0, properties_1.resolveProperties)(transaction).then(async (tx) => {
|
|
68
|
+
if (tx.from != null) {
|
|
69
|
+
if ((0, address_1.getAddress)(tx.from) !== (await this.getAddress())) {
|
|
70
|
+
throw new Error('transaction from address mismatch');
|
|
71
|
+
}
|
|
72
|
+
delete tx.from;
|
|
73
|
+
}
|
|
74
|
+
const { walletId, dfnsClient } = this.options;
|
|
75
|
+
const res = await dfnsClient.wallets.generateSignature({
|
|
76
|
+
walletId,
|
|
77
|
+
body: { kind: Wallets_1.SignatureKind.Hash, hash: (0, keccak256_1.keccak256)((0, transactions_1.serialize)(tx)) },
|
|
78
|
+
});
|
|
79
|
+
const signature = await this.waitForSignature(res.id);
|
|
80
|
+
return (0, transactions_1.serialize)(tx, signature);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async signMessage(message) {
|
|
84
|
+
const { walletId, dfnsClient } = this.options;
|
|
85
|
+
const res = await dfnsClient.wallets.generateSignature({
|
|
86
|
+
walletId,
|
|
87
|
+
body: { kind: Wallets_1.SignatureKind.Hash, hash: (0, hash_1.hashMessage)(message) },
|
|
88
|
+
});
|
|
89
|
+
return this.waitForSignature(res.id);
|
|
90
|
+
}
|
|
91
|
+
async _signTypedData(domain, types, value) {
|
|
92
|
+
// Populate any ENS names
|
|
93
|
+
const populated = await hash_1._TypedDataEncoder.resolveNames(domain, types, value, async (name) => {
|
|
94
|
+
if (!this.provider) {
|
|
95
|
+
throw new Error('cannot resolve ENS names without a provider');
|
|
96
|
+
}
|
|
97
|
+
const resolved = await this.provider.resolveName(name);
|
|
98
|
+
if (!resolved)
|
|
99
|
+
throw new Error(`unconfigured ENS name ${name}`);
|
|
100
|
+
return resolved;
|
|
101
|
+
});
|
|
102
|
+
const { walletId, dfnsClient } = this.options;
|
|
103
|
+
const res = await dfnsClient.wallets.generateSignature({
|
|
104
|
+
walletId,
|
|
105
|
+
body: {
|
|
106
|
+
kind: Wallets_1.SignatureKind.Hash,
|
|
107
|
+
hash: hash_1._TypedDataEncoder.hash(populated.domain, types, populated.value),
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
return this.waitForSignature(res.id);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.DfnsWallet = DfnsWallet;
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dfns/lib-ethersjs5",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"dependencies": {
|
|
5
|
+
"@ethersproject/abstract-provider": "5.7.0",
|
|
6
|
+
"@ethersproject/abstract-signer": "5.7.0",
|
|
7
|
+
"@ethersproject/address": "5.7.0",
|
|
8
|
+
"@ethersproject/bytes": "5.7.0",
|
|
9
|
+
"@ethersproject/hash": "5.7.0",
|
|
10
|
+
"@ethersproject/keccak256": "5.7.0",
|
|
11
|
+
"@ethersproject/properties": "5.7.0",
|
|
12
|
+
"@ethersproject/transactions": "5.7.0",
|
|
13
|
+
"buffer": "6.0.3",
|
|
14
|
+
"cross-fetch": "3.1.6",
|
|
15
|
+
"uuid": "9.0.0"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"@dfns/sdk": "0.1.0-beta.1"
|
|
19
|
+
},
|
|
20
|
+
"main": "./index.js",
|
|
21
|
+
"types": "./index.d.ts"
|
|
22
|
+
}
|