@meshsdk/wallet 1.6.0-alpha.11
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/README.md +5 -0
- package/jest.config.js +5 -0
- package/package.json +36 -0
- package/src/app/index.ts +239 -0
- package/src/browser/index.ts +440 -0
- package/src/embedded/index.ts +258 -0
- package/src/index.ts +4 -0
- package/src/mesh/index.ts +413 -0
- package/src/types/index.ts +39 -0
- package/test/app.test.ts +98 -0
- package/test/browser.test.ts +21 -0
- package/test/embedded.test.ts +137 -0
- package/test/mesh.test.ts +95 -0
- package/tsconfig.json +5 -0
package/README.md
ADDED
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meshsdk/wallet",
|
|
3
|
+
"version": "1.6.0-alpha.11",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build:mesh": "tsup src/index.ts --format esm,cjs --dts",
|
|
16
|
+
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
|
|
17
|
+
"lint": "eslint",
|
|
18
|
+
"clean": "rm -rf .turbo && rm -rf dist && rm -rf node_modules",
|
|
19
|
+
"test": "jest --verbose",
|
|
20
|
+
"format": "prettier --check . --ignore-path ../../.gitignore",
|
|
21
|
+
"build:docs": "typedoc src/index.ts --json ../../apps/docs/src/data/mesh-wallets.json"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@meshsdk/typescript-config": "*",
|
|
25
|
+
"eslint": "^8.57.0",
|
|
26
|
+
"tsup": "^8.0.2",
|
|
27
|
+
"typescript": "^5.3.3",
|
|
28
|
+
"typedoc": "^0.26.3"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@meshsdk/common": "*",
|
|
32
|
+
"@meshsdk/core-cst": "*",
|
|
33
|
+
"@meshsdk/transaction": "*"
|
|
34
|
+
},
|
|
35
|
+
"prettier": "@meshsdk/prettier-config"
|
|
36
|
+
}
|
package/src/app/index.ts
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { DataSignature, IFetcher, ISigner, ISubmitter } from "@meshsdk/common";
|
|
2
|
+
import {
|
|
3
|
+
Address,
|
|
4
|
+
deserializeTx,
|
|
5
|
+
toAddress,
|
|
6
|
+
toTxUnspentOutput,
|
|
7
|
+
TransactionUnspentOutput,
|
|
8
|
+
} from "@meshsdk/core-cst";
|
|
9
|
+
|
|
10
|
+
import { EmbeddedWallet } from "../embedded";
|
|
11
|
+
import { GetAddressType } from "../types";
|
|
12
|
+
|
|
13
|
+
export type AppWalletKeyType =
|
|
14
|
+
| {
|
|
15
|
+
type: "root";
|
|
16
|
+
bech32: string;
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
type: "cli";
|
|
20
|
+
payment: string;
|
|
21
|
+
stake?: string;
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
type: "mnemonic";
|
|
25
|
+
words: string[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type CreateAppWalletOptions = {
|
|
29
|
+
networkId: number;
|
|
30
|
+
fetcher?: IFetcher;
|
|
31
|
+
submitter?: ISubmitter;
|
|
32
|
+
key: AppWalletKeyType;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export class AppWallet implements ISigner, ISubmitter {
|
|
36
|
+
private readonly _fetcher?: IFetcher;
|
|
37
|
+
private readonly _submitter?: ISubmitter;
|
|
38
|
+
private readonly _wallet: EmbeddedWallet;
|
|
39
|
+
|
|
40
|
+
constructor(options: CreateAppWalletOptions) {
|
|
41
|
+
this._fetcher = options.fetcher;
|
|
42
|
+
this._submitter = options.submitter;
|
|
43
|
+
|
|
44
|
+
switch (options.key.type) {
|
|
45
|
+
case "mnemonic":
|
|
46
|
+
this._wallet = new EmbeddedWallet({
|
|
47
|
+
networkId: options.networkId,
|
|
48
|
+
key: {
|
|
49
|
+
type: "mnemonic",
|
|
50
|
+
words: options.key.words,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
54
|
+
case "root":
|
|
55
|
+
this._wallet = new EmbeddedWallet({
|
|
56
|
+
networkId: options.networkId,
|
|
57
|
+
key: {
|
|
58
|
+
type: "root",
|
|
59
|
+
bech32: options.key.bech32,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
63
|
+
case "cli":
|
|
64
|
+
this._wallet = new EmbeddedWallet({
|
|
65
|
+
networkId: options.networkId,
|
|
66
|
+
key: {
|
|
67
|
+
type: "cli",
|
|
68
|
+
payment: options.key.payment,
|
|
69
|
+
stake: options.key.stake,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get a list of UTXOs to be used as collateral inputs for transactions with plutus script inputs.
|
|
77
|
+
*
|
|
78
|
+
* This is used in transaction building.
|
|
79
|
+
*
|
|
80
|
+
* @returns a list of UTXOs
|
|
81
|
+
*/
|
|
82
|
+
async getCollateralUnspentOutput(
|
|
83
|
+
accountIndex = 0,
|
|
84
|
+
addressType: GetAddressType = "payment",
|
|
85
|
+
): Promise<TransactionUnspentOutput[]> {
|
|
86
|
+
const utxos = await this.getUnspentOutputs(accountIndex, addressType);
|
|
87
|
+
|
|
88
|
+
// find utxos that are pure ADA-only
|
|
89
|
+
const pureAdaUtxos = utxos.filter((utxo) => {
|
|
90
|
+
return utxo.output().amount().multiasset() === undefined;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// sort utxos by their lovelace amount
|
|
94
|
+
pureAdaUtxos.sort((a, b) => {
|
|
95
|
+
return (
|
|
96
|
+
Number(a.output().amount().coin()) - Number(b.output().amount().coin())
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// return the smallest utxo but not less than 5000000 lovelace
|
|
101
|
+
for (const utxo of pureAdaUtxos) {
|
|
102
|
+
if (Number(utxo.output().amount().coin()) >= 5000000) {
|
|
103
|
+
return [utxo];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
getEnterpriseAddress(accountIndex = 0, keyIndex = 0): string {
|
|
111
|
+
const account = this._wallet.getAccount(accountIndex, keyIndex);
|
|
112
|
+
return account.enterpriseAddressBech32;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
getPaymentAddress(accountIndex = 0, keyIndex = 0): string {
|
|
116
|
+
const account = this._wallet.getAccount(accountIndex, keyIndex);
|
|
117
|
+
return account.baseAddressBech32;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getRewardAddress(accountIndex = 0, keyIndex = 0): string {
|
|
121
|
+
const account = this._wallet.getAccount(accountIndex, keyIndex);
|
|
122
|
+
return account.rewardAddressBech32;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
getNetworkId(): number {
|
|
126
|
+
return this._wallet.getNetworkId();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
getUsedAddress(
|
|
130
|
+
accountIndex = 0,
|
|
131
|
+
keyIndex = 0,
|
|
132
|
+
addressType: GetAddressType = "payment",
|
|
133
|
+
): Address {
|
|
134
|
+
if (addressType === "enterprise") {
|
|
135
|
+
return toAddress(this.getEnterpriseAddress(accountIndex, keyIndex));
|
|
136
|
+
} else {
|
|
137
|
+
return toAddress(this.getPaymentAddress(accountIndex, keyIndex));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async getUnspentOutputs(
|
|
142
|
+
accountIndex = 0,
|
|
143
|
+
addressType: GetAddressType = "payment",
|
|
144
|
+
): Promise<TransactionUnspentOutput[]> {
|
|
145
|
+
if (!this._fetcher) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
"[AppWallet] Fetcher is required to fetch UTxOs. Please provide a fetcher.",
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
const account = this._wallet.getAccount(accountIndex);
|
|
151
|
+
|
|
152
|
+
const utxos = await this._fetcher.fetchAddressUTxOs(
|
|
153
|
+
addressType == "enterprise"
|
|
154
|
+
? account.enterpriseAddressBech32
|
|
155
|
+
: account.baseAddressBech32,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
return utxos.map((utxo) => toTxUnspentOutput(utxo));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
signData(
|
|
162
|
+
address: string,
|
|
163
|
+
payload: string,
|
|
164
|
+
accountIndex = 0,
|
|
165
|
+
keyIndex = 0,
|
|
166
|
+
): DataSignature {
|
|
167
|
+
try {
|
|
168
|
+
return this._wallet.signData(address, payload, accountIndex, keyIndex);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
`[AppWallet] An error occurred during signData: ${error}.`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
signTx(
|
|
177
|
+
unsignedTx: string,
|
|
178
|
+
partialSign = false,
|
|
179
|
+
accountIndex = 0,
|
|
180
|
+
keyIndex = 0,
|
|
181
|
+
): string {
|
|
182
|
+
try {
|
|
183
|
+
const tx = deserializeTx(unsignedTx);
|
|
184
|
+
if (
|
|
185
|
+
!partialSign &&
|
|
186
|
+
tx.witnessSet().vkeys() !== undefined &&
|
|
187
|
+
tx.witnessSet().vkeys()!.size() !== 0
|
|
188
|
+
)
|
|
189
|
+
throw new Error(
|
|
190
|
+
"Signatures already exist in the transaction in a non partial sign call",
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
const newSignatures = this._wallet.signTx(
|
|
194
|
+
unsignedTx,
|
|
195
|
+
accountIndex,
|
|
196
|
+
keyIndex,
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
let signedTx = EmbeddedWallet.addWitnessSets(unsignedTx, [newSignatures]);
|
|
200
|
+
return signedTx;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
throw new Error(`[AppWallet] An error occurred during signTx: ${error}.`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
signTxSync(
|
|
207
|
+
unsignedTx: string,
|
|
208
|
+
partialSign = false,
|
|
209
|
+
accountIndex = 0,
|
|
210
|
+
keyIndex = 0,
|
|
211
|
+
): string {
|
|
212
|
+
try {
|
|
213
|
+
// todo
|
|
214
|
+
return "signedTx";
|
|
215
|
+
} catch (error) {
|
|
216
|
+
throw new Error(`[AppWallet] An error occurred during signTx: ${error}.`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async signTxs(
|
|
221
|
+
unsignedTxs: string[],
|
|
222
|
+
partialSign: boolean,
|
|
223
|
+
): Promise<string[]> {
|
|
224
|
+
throw new Error(`[AppWallet] signTxs() is not implemented.`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
submitTx(tx: string): Promise<string> {
|
|
228
|
+
if (!this._submitter) {
|
|
229
|
+
throw new Error(
|
|
230
|
+
"[AppWallet] Submitter is required to submit transactions. Please provide a submitter.",
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return this._submitter.submitTx(tx);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
static brew(strength = 256): string[] {
|
|
237
|
+
return EmbeddedWallet.generateMnemonic(strength);
|
|
238
|
+
}
|
|
239
|
+
}
|