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