@dynamic-labs/starknet 4.0.0-alpha.27 → 4.0.0-alpha.29
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/CHANGELOG.md +21 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +14 -11
- package/src/StarknetWalletConnector.cjs +233 -0
- package/src/StarknetWalletConnector.d.ts +58 -0
- package/src/StarknetWalletConnector.js +229 -0
- package/src/getAvailableWallets.cjs +27 -0
- package/src/getAvailableWallets.d.ts +8 -0
- package/src/getAvailableWallets.js +21 -0
- package/src/index.cjs +12 -13
- package/src/index.d.ts +16 -7
- package/src/index.js +11 -13
- package/src/types.d.ts +26 -11
- package/src/utils/convertors.cjs +1 -1
- package/src/utils/convertors.d.ts +1 -1
- package/src/utils/convertors.js +1 -1
- package/src/utils/starknetSnap.d.ts +2 -2
- package/src/wallet/StarknetWallet.cjs +0 -3
- package/src/wallet/StarknetWallet.d.ts +4 -4
- package/src/wallet/StarknetWallet.js +0 -3
- package/src/wallets/argent/argentMobile/argentMobile.cjs +73 -0
- package/src/wallets/argent/argentMobile/argentMobile.d.ts +16 -0
- package/src/wallets/argent/argentMobile/argentMobile.js +69 -0
- package/src/wallets/argent/base.cjs +50 -0
- package/src/wallets/argent/base.d.ts +5 -0
- package/src/wallets/argent/base.js +46 -0
- package/src/wallets/argent/injected/argentx.cjs +33 -0
- package/src/wallets/argent/injected/argentx.d.ts +8 -0
- package/src/wallets/argent/injected/argentx.js +29 -0
- package/src/wallets/argent/webwallet/webwallet.cjs +37 -0
- package/src/wallets/argent/webwallet/webwallet.d.ts +10 -0
- package/src/wallets/argent/webwallet/webwallet.js +33 -0
- package/src/wallets/injected/fetchStarknetInjectedWalletConnectors.cjs +34 -0
- package/src/wallets/injected/fetchStarknetInjectedWalletConnectors.d.ts +5 -0
- package/src/wallets/injected/fetchStarknetInjectedWalletConnectors.js +30 -0
- package/src/wallets/injected/injected.cjs +138 -0
- package/src/wallets/injected/injected.d.ts +9 -0
- package/src/wallets/injected/injected.js +134 -0
- package/src/wallets/{metamask.d.ts → injected/metamask.d.ts} +2 -4
- package/src/starknetWalletConnector.cjs +0 -320
- package/src/starknetWalletConnector.d.ts +0 -128
- package/src/starknetWalletConnector.js +0 -314
- package/src/utils/starknetSnap.cjs +0 -92
- package/src/utils/starknetSnap.js +0 -88
- package/src/wallets/argentx.cjs +0 -24
- package/src/wallets/argentx.d.ts +0 -8
- package/src/wallets/argentx.js +0 -20
- package/src/wallets/argentxBase.cjs +0 -50
- package/src/wallets/argentxBase.d.ts +0 -16
- package/src/wallets/argentxBase.js +0 -48
- package/src/wallets/argentxMobile.cjs +0 -100
- package/src/wallets/argentxMobile.d.ts +0 -13
- package/src/wallets/argentxMobile.js +0 -96
- package/src/wallets/argentxWeb.cjs +0 -57
- package/src/wallets/argentxWeb.d.ts +0 -8
- package/src/wallets/argentxWeb.js +0 -53
- package/src/wallets/bitget.cjs +0 -22
- package/src/wallets/bitget.d.ts +0 -7
- package/src/wallets/bitget.js +0 -18
- package/src/wallets/braavos.cjs +0 -37
- package/src/wallets/braavos.d.ts +0 -8
- package/src/wallets/braavos.js +0 -33
- package/src/wallets/metamask.cjs +0 -121
- package/src/wallets/metamask.js +0 -117
- package/src/wallets/okx.cjs +0 -15
- package/src/wallets/okx.d.ts +0 -6
- package/src/wallets/okx.js +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
|
|
2
|
+
## [4.0.0-alpha.29](https://github.com/dynamic-labs/dynamic-auth/compare/v4.0.0-alpha.28...v4.0.0-alpha.29) (2024-11-07)
|
|
3
|
+
|
|
4
|
+
## [4.0.0-alpha.28](https://github.com/dynamic-labs/dynamic-auth/compare/v4.0.0-alpha.27...v4.0.0-alpha.28) (2024-11-07)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
### ⚠ BREAKING CHANGES
|
|
8
|
+
|
|
9
|
+
* upgrade to starknet v6
|
|
10
|
+
See this guide for more details: https://starknetjs.com/docs/guides/migrate/
|
|
11
|
+
There are no code changes required on the Dynamic SDK side, however if you have installed the `starknet` package, you will need to upgrade to >= v6.11.0.
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* new transaction modal and ui for sign/signAll ([#7296](https://github.com/dynamic-labs/dynamic-auth/issues/7296)) ([05a8af1](https://github.com/dynamic-labs/dynamic-auth/commit/05a8af1eb772b2b8087ed96a54caf4b6ae8b79d2)), closes [#7297](https://github.com/dynamic-labs/dynamic-auth/issues/7297) [#7298](https://github.com/dynamic-labs/dynamic-auth/issues/7298)
|
|
16
|
+
* upgrade to starknet v6 ([#7189](https://github.com/dynamic-labs/dynamic-auth/issues/7189)) ([2a6e24e](https://github.com/dynamic-labs/dynamic-auth/commit/2a6e24e4178fcee671b381c28f6a681f4ce52c62))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* transaction confirmation modal popup ([#7368](https://github.com/dynamic-labs/dynamic-auth/issues/7368)) ([3c48658](https://github.com/dynamic-labs/dynamic-auth/commit/3c48658a62874d908bba8f06fb092ff5983ede16))
|
|
22
|
+
|
|
2
23
|
## [4.0.0-alpha.27](https://github.com/dynamic-labs/dynamic-auth/compare/v4.0.0-alpha.26...v4.0.0-alpha.27) (2024-11-06)
|
|
3
24
|
|
|
4
25
|
|
package/package.cjs
CHANGED
package/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/starknet",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.29",
|
|
4
4
|
"description": "A React SDK for implementing wallet web3 authentication and authorization to your website.",
|
|
5
5
|
"author": "Dynamic Labs, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,18 +18,21 @@
|
|
|
18
18
|
},
|
|
19
19
|
"homepage": "https://www.dynamic.xyz/",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"starknet": "
|
|
22
|
-
"
|
|
21
|
+
"@starknet-io/get-starknet-core": "4.0.3",
|
|
22
|
+
"@starknet-io/types-js": "0.7.7",
|
|
23
|
+
"starknet": "6.11.0",
|
|
24
|
+
"starknetkit": "2.3.3",
|
|
23
25
|
"text-encoding": "0.7.0",
|
|
24
|
-
"
|
|
25
|
-
"@dynamic-labs/sdk-api-core": "0.0.559",
|
|
26
|
+
"@dynamic-labs/sdk-api-core": "0.0.563",
|
|
26
27
|
"@module-federation/runtime": "0.1.18",
|
|
27
|
-
"@dynamic-labs/assert-package-version": "4.0.0-alpha.
|
|
28
|
-
"@dynamic-labs/logger": "4.0.0-alpha.
|
|
29
|
-
"@dynamic-labs/
|
|
30
|
-
"@dynamic-labs/
|
|
31
|
-
"@dynamic-labs/
|
|
32
|
-
"@dynamic-labs/wallet-
|
|
28
|
+
"@dynamic-labs/assert-package-version": "4.0.0-alpha.29",
|
|
29
|
+
"@dynamic-labs/logger": "4.0.0-alpha.29",
|
|
30
|
+
"@dynamic-labs/rpc-providers": "4.0.0-alpha.29",
|
|
31
|
+
"@dynamic-labs/starknet-core": "4.0.0-alpha.29",
|
|
32
|
+
"@dynamic-labs/utils": "4.0.0-alpha.29",
|
|
33
|
+
"@dynamic-labs/wallet-book": "4.0.0-alpha.29",
|
|
34
|
+
"@dynamic-labs/wallet-connector-core": "4.0.0-alpha.29",
|
|
35
|
+
"assert": "2.1.0"
|
|
33
36
|
},
|
|
34
37
|
"peerDependencies": {}
|
|
35
38
|
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var _tslib = require('../_virtual/_tslib.cjs');
|
|
7
|
+
var starknet = require('starknet');
|
|
8
|
+
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
9
|
+
var utils = require('@dynamic-labs/utils');
|
|
10
|
+
var logger = require('@dynamic-labs/logger');
|
|
11
|
+
var constants = require('./constants.cjs');
|
|
12
|
+
var ethereumContractAbi = require('./ethereumContractAbi.cjs');
|
|
13
|
+
var convertors = require('./utils/convertors.cjs');
|
|
14
|
+
var StarknetWallet = require('./wallet/StarknetWallet.cjs');
|
|
15
|
+
var getAvailableWallets = require('./getAvailableWallets.cjs');
|
|
16
|
+
|
|
17
|
+
class StarknetWalletConnector extends walletConnectorCore.WalletConnectorBase {
|
|
18
|
+
constructor(name, id, opts) {
|
|
19
|
+
var _a;
|
|
20
|
+
super(opts);
|
|
21
|
+
this.ChainWallet = StarknetWallet.StarknetWallet;
|
|
22
|
+
this.connectedChain = 'STARK';
|
|
23
|
+
this.supportedChains = ['STARK'];
|
|
24
|
+
this.switchNetworkOnlyFromWallet = true;
|
|
25
|
+
/** required for metamask snap integration as MM snaps don't have event listeners */
|
|
26
|
+
this.canSetEventListeners = true;
|
|
27
|
+
this.name = name;
|
|
28
|
+
this.id = id;
|
|
29
|
+
this.starknetNetworks = opts.starknetNetworks;
|
|
30
|
+
this.chainRpcProviders = opts.chainRpcProviders;
|
|
31
|
+
(_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerStarknetProviders();
|
|
32
|
+
this.walletBookWallet = opts.walletBookWallet;
|
|
33
|
+
this.logger = new logger.Logger(this.name);
|
|
34
|
+
}
|
|
35
|
+
connect() {
|
|
36
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
yield this.getAddress();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
getAddress() {
|
|
41
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
var _a;
|
|
43
|
+
if ((_a = this.walletData) === null || _a === void 0 ? void 0 : _a.account) {
|
|
44
|
+
return this.walletData.account;
|
|
45
|
+
}
|
|
46
|
+
this.logger.debug('[getAddress] Prompting new connection');
|
|
47
|
+
const { wallet, data } = yield this.prompt({
|
|
48
|
+
silently: false,
|
|
49
|
+
});
|
|
50
|
+
this.logger.debug(`[getAddress] Connection returned account: ${data === null || data === void 0 ? void 0 : data.account}, wallet: ${wallet}`);
|
|
51
|
+
if (!wallet || !data) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
this.wallet = wallet;
|
|
55
|
+
this.walletData = data;
|
|
56
|
+
this.setupEventListeners();
|
|
57
|
+
return this.walletData.account;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* returns starknet wallet network id
|
|
62
|
+
*/
|
|
63
|
+
getNetwork() {
|
|
64
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
var _a;
|
|
66
|
+
if (!((_a = this.walletData) === null || _a === void 0 ? void 0 : _a.chainId)) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return starknet.num.toHex(this.walletData.chainId);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
getBalance(address) {
|
|
73
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
const wallet = yield this.getWalletAccount();
|
|
75
|
+
if (!wallet) {
|
|
76
|
+
this.logger.error('Could not find provider for getting balance');
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
const contract = new starknet.Contract(ethereumContractAbi, constants.ETH_STARKNET_ADDRESS, wallet);
|
|
80
|
+
try {
|
|
81
|
+
const { balance } = yield contract.balanceOf(address);
|
|
82
|
+
/**
|
|
83
|
+
* Dividing by 1e18 as the returned balance is a Gwei number.
|
|
84
|
+
* Read more here: https://www.investopedia.com/terms/g/gwei-ethereum.asp#toc-what-is-gwei
|
|
85
|
+
*/
|
|
86
|
+
return (Number(starknet.cairo.uint256(balance.low).low) / 1e18).toFixed(6);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
this.logger.error(error);
|
|
90
|
+
throw new utils.DynamicError('Something went wrong');
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
signMessage(messageToSign) {
|
|
95
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
const [walletAddress, chainId] = yield Promise.all([
|
|
97
|
+
this.getAddress(),
|
|
98
|
+
this.getNetwork(),
|
|
99
|
+
]);
|
|
100
|
+
const assertions = [
|
|
101
|
+
[walletAddress, 'No address for wallet'],
|
|
102
|
+
[chainId, 'No chainId for wallet'],
|
|
103
|
+
[this.wallet, 'No wallet provider'],
|
|
104
|
+
];
|
|
105
|
+
for (const [value, message] of assertions) {
|
|
106
|
+
if (!value) {
|
|
107
|
+
this.logger.error(`[signMessage] ${message}. Make sure \`connect\` was called first`);
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const encodedMessage = convertors.formatTypedDataMessage(messageToSign, chainId);
|
|
112
|
+
// justification: performing assertion above
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
114
|
+
const signature = yield this.wallet.request({
|
|
115
|
+
params: encodedMessage,
|
|
116
|
+
type: 'wallet_signTypedData',
|
|
117
|
+
});
|
|
118
|
+
return signature === null || signature === void 0 ? void 0 : signature.join(',');
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
getWalletAccount() {
|
|
122
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
123
|
+
if (!this.wallet) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
return new starknet.WalletAccount(yield this.getProvider(), this.wallet);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
getProvider() {
|
|
130
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
const rpcUrl = yield this.resolveRpcUrl();
|
|
132
|
+
this.logger.debug(`[getProvider] using rpcUrl: ${rpcUrl}`);
|
|
133
|
+
return new starknet.RpcProvider({ nodeUrl: rpcUrl });
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
isInstalledOnBrowser() {
|
|
137
|
+
return Boolean(getAvailableWallets.availableWallets.find((wallet) => wallet.id === this.id));
|
|
138
|
+
}
|
|
139
|
+
endSession() {
|
|
140
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
141
|
+
this.teardownEventListeners();
|
|
142
|
+
this.wallet = undefined;
|
|
143
|
+
this.walletData = undefined;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
setupEventListeners() {
|
|
147
|
+
if (!this.canSetEventListeners)
|
|
148
|
+
return;
|
|
149
|
+
if (!this.wallet) {
|
|
150
|
+
this.logger.debug('[setupEventListeners] Not connected, returning early');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
this.handleAccountChange = (accounts) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
var _a;
|
|
155
|
+
this.logger.debug(`[accountsChanged] Received argument: ${accounts === null || accounts === void 0 ? void 0 : accounts.toString()}`);
|
|
156
|
+
if (!accounts || accounts[0] === null) {
|
|
157
|
+
this.emit('disconnect');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const [address] = accounts;
|
|
161
|
+
if (address) {
|
|
162
|
+
this.walletData = {
|
|
163
|
+
account: address,
|
|
164
|
+
chainId: (_a = this.walletData) === null || _a === void 0 ? void 0 : _a.chainId,
|
|
165
|
+
};
|
|
166
|
+
this.emit('accountChange', { accounts: [address.toString()] });
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
this.handleNetworkChange = (chainId) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
170
|
+
var _b;
|
|
171
|
+
this.logger.debug(`[networkChanged] Received argument: ${chainId === null || chainId === void 0 ? void 0 : chainId.toString()}`);
|
|
172
|
+
if (!chainId) {
|
|
173
|
+
this.emit('disconnect');
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
this.walletData = {
|
|
177
|
+
account: (_b = this.walletData) === null || _b === void 0 ? void 0 : _b.account,
|
|
178
|
+
chainId: BigInt(chainId),
|
|
179
|
+
};
|
|
180
|
+
this.emit('chainChange', { chain: chainId });
|
|
181
|
+
});
|
|
182
|
+
this.logger.debug('[setupEventListeners] Setting up accountsChanged and networkChanged');
|
|
183
|
+
this.wallet.on('accountsChanged', this.handleAccountChange);
|
|
184
|
+
this.wallet.on('networkChanged', this.handleNetworkChange);
|
|
185
|
+
}
|
|
186
|
+
teardownEventListeners() {
|
|
187
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
var _a, _b;
|
|
189
|
+
if (!this.canSetEventListeners)
|
|
190
|
+
return;
|
|
191
|
+
if (this.handleAccountChange) {
|
|
192
|
+
(_a = this.wallet) === null || _a === void 0 ? void 0 : _a.off('accountsChanged', this.handleAccountChange);
|
|
193
|
+
this.handleAccountChange = undefined;
|
|
194
|
+
}
|
|
195
|
+
if (this.handleNetworkChange) {
|
|
196
|
+
(_b = this.wallet) === null || _b === void 0 ? void 0 : _b.off('networkChanged', this.handleNetworkChange);
|
|
197
|
+
this.handleNetworkChange = undefined;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
resolveRpcUrl() {
|
|
202
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
203
|
+
var _a;
|
|
204
|
+
const chainId = yield this.getNetwork();
|
|
205
|
+
if (!chainId) {
|
|
206
|
+
this.logger.warn('[resolveRpcUrl] `getNetwork` returned undefined');
|
|
207
|
+
return undefined;
|
|
208
|
+
}
|
|
209
|
+
const networkConfig = this.starknetNetworks.find((config) => config.chainId === chainId);
|
|
210
|
+
if (!networkConfig) {
|
|
211
|
+
this.logger.warn(`[resolveRpcUrl] Network configuration for chainId \`${chainId}\` is not found in starknetNetworks`);
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
return (((_a = networkConfig.privateCustomerRpcUrls) === null || _a === void 0 ? void 0 : _a[0]) || networkConfig.rpcUrls[0]);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
mapChainIdToNetworkName(chainIdOrNetworkName) {
|
|
218
|
+
if (chainIdOrNetworkName === starknet.constants.StarknetChainId.SN_MAIN ||
|
|
219
|
+
chainIdOrNetworkName === starknet.constants.NetworkName.SN_MAIN) {
|
|
220
|
+
return starknet.constants.NetworkName.SN_MAIN;
|
|
221
|
+
}
|
|
222
|
+
else if (chainIdOrNetworkName === starknet.constants.StarknetChainId.SN_SEPOLIA ||
|
|
223
|
+
chainIdOrNetworkName === starknet.constants.NetworkName.SN_SEPOLIA) {
|
|
224
|
+
return starknet.constants.NetworkName.SN_SEPOLIA;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
this.logger.error('Unknown chainId', chainIdOrNetworkName);
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
exports.StarknetWalletConnector = StarknetWalletConnector;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { constants, WalletAccount, RpcProvider } from 'starknet';
|
|
2
|
+
import { WALLET_API, StarknetWindowObject } from '@starknet-io/types-js';
|
|
3
|
+
import { Chain, WalletConnectorBase } from '@dynamic-labs/wallet-connector-core';
|
|
4
|
+
import { NetworkConfiguration } from '@dynamic-labs/sdk-api-core';
|
|
5
|
+
import { WalletSchema } from '@dynamic-labs/wallet-book';
|
|
6
|
+
import { Logger } from '@dynamic-labs/logger';
|
|
7
|
+
import { PromptOptions, PromptResult, StarknetWalletConnectorProps, WalletData } from './types';
|
|
8
|
+
import { StarknetWallet } from './wallet';
|
|
9
|
+
export declare abstract class StarknetWalletConnector extends WalletConnectorBase<typeof StarknetWallet> {
|
|
10
|
+
/** the name of the connector, e.g. "Argent X", "Braavos" */
|
|
11
|
+
name: string;
|
|
12
|
+
/**
|
|
13
|
+
* the string identifier of the connector as surfaced by `get-starknet-core` or `starknetkit`
|
|
14
|
+
* this is used to prompt the correct extension, e.g. the argentX browser extension
|
|
15
|
+
*/
|
|
16
|
+
id: string;
|
|
17
|
+
ChainWallet: typeof StarknetWallet;
|
|
18
|
+
connectedChain: Chain;
|
|
19
|
+
supportedChains: Chain[];
|
|
20
|
+
handleAccountChange: WALLET_API.AccountChangeEventHandler | undefined;
|
|
21
|
+
handleNetworkChange: WALLET_API.NetworkChangeEventHandler | undefined;
|
|
22
|
+
switchNetworkOnlyFromWallet: boolean;
|
|
23
|
+
/** the starknet networks configuration from redcoast */
|
|
24
|
+
starknetNetworks: NetworkConfiguration[];
|
|
25
|
+
/** required for metamask snap integration as MM snaps don't have event listeners */
|
|
26
|
+
canSetEventListeners: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* used to obtain a WalletAccount to interact with the wallet
|
|
29
|
+
*/
|
|
30
|
+
wallet: StarknetWindowObject | undefined;
|
|
31
|
+
/** The wallet metadata. Replace with _metadata once inAppBrowser is migrated */
|
|
32
|
+
protected walletBookWallet: WalletSchema;
|
|
33
|
+
/**
|
|
34
|
+
* used to track wallet state (account and chain)
|
|
35
|
+
*/
|
|
36
|
+
walletData: WalletData | undefined;
|
|
37
|
+
logger: Logger;
|
|
38
|
+
constructor(name: string, id: string, opts: StarknetWalletConnectorProps);
|
|
39
|
+
/** implementing classes should use starknetkit or get-starknet-core functions here */
|
|
40
|
+
abstract prompt(options: PromptOptions): Promise<PromptResult>;
|
|
41
|
+
connect(): Promise<void>;
|
|
42
|
+
getAddress(): Promise<string | undefined>;
|
|
43
|
+
/**
|
|
44
|
+
* returns starknet wallet network id
|
|
45
|
+
*/
|
|
46
|
+
getNetwork(): Promise<string | undefined>;
|
|
47
|
+
getBalance(address: string): Promise<string | undefined>;
|
|
48
|
+
signMessage(messageToSign: string): Promise<string | undefined>;
|
|
49
|
+
getWalletAccount(): Promise<WalletAccount | undefined>;
|
|
50
|
+
getProvider(): Promise<RpcProvider>;
|
|
51
|
+
isInstalledOnBrowser(): boolean;
|
|
52
|
+
endSession(): Promise<void>;
|
|
53
|
+
setupEventListeners(): void;
|
|
54
|
+
teardownEventListeners(): Promise<void>;
|
|
55
|
+
protected resolveRpcUrl(): Promise<string | undefined>;
|
|
56
|
+
protected mapChainIdToNetworkName(chainIdOrNetworkName: string): constants.NetworkName | undefined;
|
|
57
|
+
}
|
|
58
|
+
export type StarknetWalletConnectorType = StarknetWalletConnector;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../_virtual/_tslib.js';
|
|
3
|
+
import { constants, num, Contract, cairo, WalletAccount, RpcProvider } from 'starknet';
|
|
4
|
+
import { WalletConnectorBase } from '@dynamic-labs/wallet-connector-core';
|
|
5
|
+
import { DynamicError } from '@dynamic-labs/utils';
|
|
6
|
+
import { Logger } from '@dynamic-labs/logger';
|
|
7
|
+
import { ETH_STARKNET_ADDRESS } from './constants.js';
|
|
8
|
+
import ETH_CONTRACT_ABI from './ethereumContractAbi.js';
|
|
9
|
+
import { formatTypedDataMessage } from './utils/convertors.js';
|
|
10
|
+
import { StarknetWallet } from './wallet/StarknetWallet.js';
|
|
11
|
+
import { availableWallets } from './getAvailableWallets.js';
|
|
12
|
+
|
|
13
|
+
class StarknetWalletConnector extends WalletConnectorBase {
|
|
14
|
+
constructor(name, id, opts) {
|
|
15
|
+
var _a;
|
|
16
|
+
super(opts);
|
|
17
|
+
this.ChainWallet = StarknetWallet;
|
|
18
|
+
this.connectedChain = 'STARK';
|
|
19
|
+
this.supportedChains = ['STARK'];
|
|
20
|
+
this.switchNetworkOnlyFromWallet = true;
|
|
21
|
+
/** required for metamask snap integration as MM snaps don't have event listeners */
|
|
22
|
+
this.canSetEventListeners = true;
|
|
23
|
+
this.name = name;
|
|
24
|
+
this.id = id;
|
|
25
|
+
this.starknetNetworks = opts.starknetNetworks;
|
|
26
|
+
this.chainRpcProviders = opts.chainRpcProviders;
|
|
27
|
+
(_a = this.chainRpcProviders) === null || _a === void 0 ? void 0 : _a.registerStarknetProviders();
|
|
28
|
+
this.walletBookWallet = opts.walletBookWallet;
|
|
29
|
+
this.logger = new Logger(this.name);
|
|
30
|
+
}
|
|
31
|
+
connect() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
yield this.getAddress();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
getAddress() {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
var _a;
|
|
39
|
+
if ((_a = this.walletData) === null || _a === void 0 ? void 0 : _a.account) {
|
|
40
|
+
return this.walletData.account;
|
|
41
|
+
}
|
|
42
|
+
this.logger.debug('[getAddress] Prompting new connection');
|
|
43
|
+
const { wallet, data } = yield this.prompt({
|
|
44
|
+
silently: false,
|
|
45
|
+
});
|
|
46
|
+
this.logger.debug(`[getAddress] Connection returned account: ${data === null || data === void 0 ? void 0 : data.account}, wallet: ${wallet}`);
|
|
47
|
+
if (!wallet || !data) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
this.wallet = wallet;
|
|
51
|
+
this.walletData = data;
|
|
52
|
+
this.setupEventListeners();
|
|
53
|
+
return this.walletData.account;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* returns starknet wallet network id
|
|
58
|
+
*/
|
|
59
|
+
getNetwork() {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
var _a;
|
|
62
|
+
if (!((_a = this.walletData) === null || _a === void 0 ? void 0 : _a.chainId)) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
return num.toHex(this.walletData.chainId);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
getBalance(address) {
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
const wallet = yield this.getWalletAccount();
|
|
71
|
+
if (!wallet) {
|
|
72
|
+
this.logger.error('Could not find provider for getting balance');
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const contract = new Contract(ETH_CONTRACT_ABI, ETH_STARKNET_ADDRESS, wallet);
|
|
76
|
+
try {
|
|
77
|
+
const { balance } = yield contract.balanceOf(address);
|
|
78
|
+
/**
|
|
79
|
+
* Dividing by 1e18 as the returned balance is a Gwei number.
|
|
80
|
+
* Read more here: https://www.investopedia.com/terms/g/gwei-ethereum.asp#toc-what-is-gwei
|
|
81
|
+
*/
|
|
82
|
+
return (Number(cairo.uint256(balance.low).low) / 1e18).toFixed(6);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
this.logger.error(error);
|
|
86
|
+
throw new DynamicError('Something went wrong');
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
signMessage(messageToSign) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
const [walletAddress, chainId] = yield Promise.all([
|
|
93
|
+
this.getAddress(),
|
|
94
|
+
this.getNetwork(),
|
|
95
|
+
]);
|
|
96
|
+
const assertions = [
|
|
97
|
+
[walletAddress, 'No address for wallet'],
|
|
98
|
+
[chainId, 'No chainId for wallet'],
|
|
99
|
+
[this.wallet, 'No wallet provider'],
|
|
100
|
+
];
|
|
101
|
+
for (const [value, message] of assertions) {
|
|
102
|
+
if (!value) {
|
|
103
|
+
this.logger.error(`[signMessage] ${message}. Make sure \`connect\` was called first`);
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const encodedMessage = formatTypedDataMessage(messageToSign, chainId);
|
|
108
|
+
// justification: performing assertion above
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
110
|
+
const signature = yield this.wallet.request({
|
|
111
|
+
params: encodedMessage,
|
|
112
|
+
type: 'wallet_signTypedData',
|
|
113
|
+
});
|
|
114
|
+
return signature === null || signature === void 0 ? void 0 : signature.join(',');
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
getWalletAccount() {
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
if (!this.wallet) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return new WalletAccount(yield this.getProvider(), this.wallet);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
getProvider() {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
const rpcUrl = yield this.resolveRpcUrl();
|
|
128
|
+
this.logger.debug(`[getProvider] using rpcUrl: ${rpcUrl}`);
|
|
129
|
+
return new RpcProvider({ nodeUrl: rpcUrl });
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
isInstalledOnBrowser() {
|
|
133
|
+
return Boolean(availableWallets.find((wallet) => wallet.id === this.id));
|
|
134
|
+
}
|
|
135
|
+
endSession() {
|
|
136
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
137
|
+
this.teardownEventListeners();
|
|
138
|
+
this.wallet = undefined;
|
|
139
|
+
this.walletData = undefined;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
setupEventListeners() {
|
|
143
|
+
if (!this.canSetEventListeners)
|
|
144
|
+
return;
|
|
145
|
+
if (!this.wallet) {
|
|
146
|
+
this.logger.debug('[setupEventListeners] Not connected, returning early');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.handleAccountChange = (accounts) => __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
var _a;
|
|
151
|
+
this.logger.debug(`[accountsChanged] Received argument: ${accounts === null || accounts === void 0 ? void 0 : accounts.toString()}`);
|
|
152
|
+
if (!accounts || accounts[0] === null) {
|
|
153
|
+
this.emit('disconnect');
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const [address] = accounts;
|
|
157
|
+
if (address) {
|
|
158
|
+
this.walletData = {
|
|
159
|
+
account: address,
|
|
160
|
+
chainId: (_a = this.walletData) === null || _a === void 0 ? void 0 : _a.chainId,
|
|
161
|
+
};
|
|
162
|
+
this.emit('accountChange', { accounts: [address.toString()] });
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
this.handleNetworkChange = (chainId) => __awaiter(this, void 0, void 0, function* () {
|
|
166
|
+
var _b;
|
|
167
|
+
this.logger.debug(`[networkChanged] Received argument: ${chainId === null || chainId === void 0 ? void 0 : chainId.toString()}`);
|
|
168
|
+
if (!chainId) {
|
|
169
|
+
this.emit('disconnect');
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.walletData = {
|
|
173
|
+
account: (_b = this.walletData) === null || _b === void 0 ? void 0 : _b.account,
|
|
174
|
+
chainId: BigInt(chainId),
|
|
175
|
+
};
|
|
176
|
+
this.emit('chainChange', { chain: chainId });
|
|
177
|
+
});
|
|
178
|
+
this.logger.debug('[setupEventListeners] Setting up accountsChanged and networkChanged');
|
|
179
|
+
this.wallet.on('accountsChanged', this.handleAccountChange);
|
|
180
|
+
this.wallet.on('networkChanged', this.handleNetworkChange);
|
|
181
|
+
}
|
|
182
|
+
teardownEventListeners() {
|
|
183
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
184
|
+
var _a, _b;
|
|
185
|
+
if (!this.canSetEventListeners)
|
|
186
|
+
return;
|
|
187
|
+
if (this.handleAccountChange) {
|
|
188
|
+
(_a = this.wallet) === null || _a === void 0 ? void 0 : _a.off('accountsChanged', this.handleAccountChange);
|
|
189
|
+
this.handleAccountChange = undefined;
|
|
190
|
+
}
|
|
191
|
+
if (this.handleNetworkChange) {
|
|
192
|
+
(_b = this.wallet) === null || _b === void 0 ? void 0 : _b.off('networkChanged', this.handleNetworkChange);
|
|
193
|
+
this.handleNetworkChange = undefined;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
resolveRpcUrl() {
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
var _a;
|
|
200
|
+
const chainId = yield this.getNetwork();
|
|
201
|
+
if (!chainId) {
|
|
202
|
+
this.logger.warn('[resolveRpcUrl] `getNetwork` returned undefined');
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
const networkConfig = this.starknetNetworks.find((config) => config.chainId === chainId);
|
|
206
|
+
if (!networkConfig) {
|
|
207
|
+
this.logger.warn(`[resolveRpcUrl] Network configuration for chainId \`${chainId}\` is not found in starknetNetworks`);
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
return (((_a = networkConfig.privateCustomerRpcUrls) === null || _a === void 0 ? void 0 : _a[0]) || networkConfig.rpcUrls[0]);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
mapChainIdToNetworkName(chainIdOrNetworkName) {
|
|
214
|
+
if (chainIdOrNetworkName === constants.StarknetChainId.SN_MAIN ||
|
|
215
|
+
chainIdOrNetworkName === constants.NetworkName.SN_MAIN) {
|
|
216
|
+
return constants.NetworkName.SN_MAIN;
|
|
217
|
+
}
|
|
218
|
+
else if (chainIdOrNetworkName === constants.StarknetChainId.SN_SEPOLIA ||
|
|
219
|
+
chainIdOrNetworkName === constants.NetworkName.SN_SEPOLIA) {
|
|
220
|
+
return constants.NetworkName.SN_SEPOLIA;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
this.logger.error('Unknown chainId', chainIdOrNetworkName);
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export { StarknetWalletConnector };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var starknetCore = require('@starknet-io/get-starknet-core');
|
|
7
|
+
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
8
|
+
|
|
9
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
|
+
|
|
11
|
+
var starknetCore__default = /*#__PURE__*/_interopDefaultLegacy(starknetCore);
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* side effect. figure out a better way to do this
|
|
15
|
+
* this is used in the `isInstalledOnBrowser` check
|
|
16
|
+
* `availableWallets` will be asyncronously populated with starknet wallets
|
|
17
|
+
* that are found on the `window`
|
|
18
|
+
*/
|
|
19
|
+
exports.availableWallets = [];
|
|
20
|
+
starknetCore__default["default"]
|
|
21
|
+
.getAvailableWallets()
|
|
22
|
+
.then((wallets) => {
|
|
23
|
+
exports.availableWallets = wallets;
|
|
24
|
+
})
|
|
25
|
+
.catch((error) => {
|
|
26
|
+
walletConnectorCore.logger.error('Failed to initialize Starknet wallets:', error);
|
|
27
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StarknetWindowObject } from 'starknetkit';
|
|
2
|
+
/**
|
|
3
|
+
* side effect. figure out a better way to do this
|
|
4
|
+
* this is used in the `isInstalledOnBrowser` check
|
|
5
|
+
* `availableWallets` will be asyncronously populated with starknet wallets
|
|
6
|
+
* that are found on the `window`
|
|
7
|
+
*/
|
|
8
|
+
export declare let availableWallets: StarknetWindowObject[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import starknetCore from '@starknet-io/get-starknet-core';
|
|
3
|
+
import { logger } from '@dynamic-labs/wallet-connector-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* side effect. figure out a better way to do this
|
|
7
|
+
* this is used in the `isInstalledOnBrowser` check
|
|
8
|
+
* `availableWallets` will be asyncronously populated with starknet wallets
|
|
9
|
+
* that are found on the `window`
|
|
10
|
+
*/
|
|
11
|
+
let availableWallets = [];
|
|
12
|
+
starknetCore
|
|
13
|
+
.getAvailableWallets()
|
|
14
|
+
.then((wallets) => {
|
|
15
|
+
availableWallets = wallets;
|
|
16
|
+
})
|
|
17
|
+
.catch((error) => {
|
|
18
|
+
logger.error('Failed to initialize Starknet wallets:', error);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { availableWallets };
|