@elizaos/plugin-wallet 2.0.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/LICENSE +21 -0
- package/README.md +64 -0
- package/auto-enable.ts +76 -0
- package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
- package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
- package/dist/aerodrome-CfnESC32.mjs +890 -0
- package/dist/chunk-hT5z_Zn9.mjs +35 -0
- package/dist/index.d.mts +34727 -0
- package/dist/index.mjs +21590 -0
- package/dist/lib/server-wallet-trade.d.mts +34 -0
- package/dist/lib/server-wallet-trade.mjs +306 -0
- package/dist/meteora-BPX39hZo.mjs +22640 -0
- package/dist/orca-Bybp1HXO.mjs +249 -0
- package/dist/pancakeswp-CkEXlXti.mjs +604 -0
- package/dist/plugin-ZO_MTyd0.mjs +529 -0
- package/dist/raydium-rfaM9yEf.mjs +539 -0
- package/dist/sdk/index.d.mts +32492 -0
- package/dist/sdk/index.mjs +6415 -0
- package/dist/types-D5252NZk.mjs +487 -0
- package/dist/uniswap-CReXgXVN.mjs +573 -0
- package/dist/wallet-action.d.mts +6 -0
- package/dist/wallet-action.mjs +820 -0
- package/package.json +152 -0
- package/src/actions/failure-codes.ts +79 -0
- package/src/actions/index.ts +1 -0
- package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
- package/src/analytics/birdeye/birdeye-task.ts +175 -0
- package/src/analytics/birdeye/birdeye.ts +813 -0
- package/src/analytics/birdeye/constants.ts +74 -0
- package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
- package/src/analytics/birdeye/providers/market.ts +227 -0
- package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
- package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
- package/src/analytics/birdeye/providers/trending.ts +365 -0
- package/src/analytics/birdeye/providers/wallet.ts +14 -0
- package/src/analytics/birdeye/search-category.test.ts +207 -0
- package/src/analytics/birdeye/search-category.ts +506 -0
- package/src/analytics/birdeye/service.ts +992 -0
- package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
- package/src/analytics/birdeye/types/api/common.ts +305 -0
- package/src/analytics/birdeye/types/api/defi.ts +220 -0
- package/src/analytics/birdeye/types/api/pair.ts +200 -0
- package/src/analytics/birdeye/types/api/search.ts +86 -0
- package/src/analytics/birdeye/types/api/token.ts +635 -0
- package/src/analytics/birdeye/types/api/trader.ts +76 -0
- package/src/analytics/birdeye/types/api/wallet.ts +181 -0
- package/src/analytics/birdeye/types/shared.ts +106 -0
- package/src/analytics/birdeye/utils.ts +700 -0
- package/src/analytics/dexscreener/errors.ts +28 -0
- package/src/analytics/dexscreener/index.ts +3 -0
- package/src/analytics/dexscreener/search-category.test.ts +49 -0
- package/src/analytics/dexscreener/search-category.ts +42 -0
- package/src/analytics/dexscreener/service.ts +595 -0
- package/src/analytics/dexscreener/types.ts +128 -0
- package/src/analytics/lpinfo/index.d.ts +7 -0
- package/src/analytics/lpinfo/index.ts +52 -0
- package/src/analytics/lpinfo/kamino/README.md +102 -0
- package/src/analytics/lpinfo/kamino/index.ts +24 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
- package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
- package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
- package/src/analytics/lpinfo/steer/README.md +169 -0
- package/src/analytics/lpinfo/steer/index.ts +23 -0
- package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
- package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
- package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
- package/src/analytics/news/index.ts +52 -0
- package/src/analytics/news/interfaces/types.ts +222 -0
- package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
- package/src/analytics/news/services/newsDataService.ts +332 -0
- package/src/analytics/news/utils/formatters.ts +151 -0
- package/src/analytics/token-info/action.ts +240 -0
- package/src/analytics/token-info/index.ts +3 -0
- package/src/analytics/token-info/params.ts +215 -0
- package/src/analytics/token-info/providers.ts +681 -0
- package/src/analytics/token-info/service.ts +168 -0
- package/src/analytics/token-info/types.ts +74 -0
- package/src/audit/audit-log.ts +45 -0
- package/src/browser-shim/build-shim.ts +123 -0
- package/src/browser-shim/index.ts +5 -0
- package/src/browser-shim/shim.template.js +563 -0
- package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
- package/src/chains/evm/LICENSE +21 -0
- package/src/chains/evm/README.md +106 -0
- package/src/chains/evm/actions/helpers.ts +147 -0
- package/src/chains/evm/actions/swap.ts +839 -0
- package/src/chains/evm/actions/transfer.ts +254 -0
- package/src/chains/evm/biome.json +61 -0
- package/src/chains/evm/bridge-router.ts +660 -0
- package/src/chains/evm/build.ts +89 -0
- package/src/chains/evm/chain-handler.ts +416 -0
- package/src/chains/evm/constants.ts +23 -0
- package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
- package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
- package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
- package/src/chains/evm/dex/aerodrome/index.ts +34 -0
- package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
- package/src/chains/evm/dex/aerodrome/types.ts +318 -0
- package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
- package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
- package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
- package/src/chains/evm/dex/uniswap/index.ts +35 -0
- package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
- package/src/chains/evm/dex/uniswap/types.ts +390 -0
- package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
- package/src/chains/evm/generated/specs/specs.ts +151 -0
- package/src/chains/evm/gov-router.ts +250 -0
- package/src/chains/evm/index.browser.ts +16 -0
- package/src/chains/evm/index.ts +31 -0
- package/src/chains/evm/prompts.ts +193 -0
- package/src/chains/evm/providers/get-balance.ts +123 -0
- package/src/chains/evm/providers/wallet.ts +715 -0
- package/src/chains/evm/routes/sign.ts +333 -0
- package/src/chains/evm/rpc-providers.ts +410 -0
- package/src/chains/evm/service.ts +140 -0
- package/src/chains/evm/templates/index.ts +10 -0
- package/src/chains/evm/types/index.ts +432 -0
- package/src/chains/evm/vitest.config.ts +18 -0
- package/src/chains/registry.ts +668 -0
- package/src/chains/solana/README.md +367 -0
- package/src/chains/wallet-action.ts +533 -0
- package/src/chains/wallet-router.test.ts +296 -0
- package/src/contracts.ts +65 -0
- package/src/core-augmentation.ts +10 -0
- package/src/index.ts +71 -0
- package/src/lib/server-wallet-trade.ts +192 -0
- package/src/lib/wallet-export-guard.ts +330 -0
- package/src/lp/actions/liquidity.ts +827 -0
- package/src/lp/e2e/real-token-tests.ts +428 -0
- package/src/lp/e2e/scenarios.ts +470 -0
- package/src/lp/e2e/test-utils.ts +145 -0
- package/src/lp/lp-manager-entry.ts +303 -0
- package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
- package/src/lp/services/DexInteractionService.ts +226 -0
- package/src/lp/services/LpManagementService.test.ts +148 -0
- package/src/lp/services/LpManagementService.ts +632 -0
- package/src/lp/services/UserLpProfileService.ts +163 -0
- package/src/lp/services/VaultService.ts +153 -0
- package/src/lp/services/YieldOptimizationService.ts +344 -0
- package/src/lp/services/__tests__/MockLpService.ts +146 -0
- package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
- package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
- package/src/lp/types.ts +582 -0
- package/src/lp/utils/solanaClient.ts +143 -0
- package/src/plugin.ts +125 -0
- package/src/policy/policy.ts +19 -0
- package/src/providers/canonical-provider.ts +27 -0
- package/src/providers/unified-wallet-provider.ts +79 -0
- package/src/register-routes.ts +11 -0
- package/src/routes/plugin.ts +47 -0
- package/src/routes/wallet-market-overview-route.ts +869 -0
- package/src/sdk/abi.ts +258 -0
- package/src/sdk/bridge/abis.ts +126 -0
- package/src/sdk/bridge/client.ts +518 -0
- package/src/sdk/bridge/index.ts +56 -0
- package/src/sdk/bridge/solana.ts +604 -0
- package/src/sdk/bridge/types.ts +202 -0
- package/src/sdk/convenience.ts +347 -0
- package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
- package/src/sdk/escrow/types.ts +64 -0
- package/src/sdk/escrow/verifiers.ts +73 -0
- package/src/sdk/identity/erc8004.ts +692 -0
- package/src/sdk/identity/reputation.ts +449 -0
- package/src/sdk/identity/uaid.ts +497 -0
- package/src/sdk/identity/validation.ts +372 -0
- package/src/sdk/index.ts +763 -0
- package/src/sdk/policy/SpendingPolicy.ts +260 -0
- package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
- package/src/sdk/router/PaymentRouter.ts +215 -0
- package/src/sdk/router/index.ts +8 -0
- package/src/sdk/swap/SwapModule.ts +310 -0
- package/src/sdk/swap/abi.ts +117 -0
- package/src/sdk/swap/index.ts +34 -0
- package/src/sdk/swap/types.ts +135 -0
- package/src/sdk/tokens/decimals.ts +140 -0
- package/src/sdk/tokens/registry.ts +911 -0
- package/src/sdk/tokens/solana.ts +419 -0
- package/src/sdk/tokens/transfers.ts +327 -0
- package/src/sdk/types.ts +158 -0
- package/src/sdk/wallet-core.ts +115 -0
- package/src/sdk/x402/budget.ts +168 -0
- package/src/sdk/x402/chains/abstract/index.ts +280 -0
- package/src/sdk/x402/client.ts +320 -0
- package/src/sdk/x402/index.ts +46 -0
- package/src/sdk/x402/middleware.ts +92 -0
- package/src/sdk/x402/multi-asset.ts +144 -0
- package/src/sdk/x402/types.ts +156 -0
- package/src/services/wallet-backend-service.ts +328 -0
- package/src/types/wallet-router.ts +227 -0
- package/src/utils/intent-trajectory.ts +106 -0
- package/src/wallet/backend.ts +62 -0
- package/src/wallet/errors.ts +49 -0
- package/src/wallet/index.ts +27 -0
- package/src/wallet/local-eoa-backend.ts +201 -0
- package/src/wallet/pending.ts +60 -0
- package/src/wallet/select-backend.ts +47 -0
- package/src/wallet/steward-backend.ts +161 -0
- package/src/wallet-action.ts +1 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Wallet shim — runs inside an arbitrary dApp page (in MAIN world) and exposes
|
|
4
|
+
* the agent's resident keypairs as both a Solana Wallet-Standard wallet and an
|
|
5
|
+
* EIP-1193 EVM provider. All signing requests proxy back to the agent's local
|
|
6
|
+
* HTTP API (`@elizaos/plugin-wallet` sign endpoints) over fetch.
|
|
7
|
+
*
|
|
8
|
+
* The shim is consumed via `buildWalletShim({ apiBase, signToken, walletName,
|
|
9
|
+
* walletIcon, solanaPublicKey, evmAddress })` which substitutes the placeholder
|
|
10
|
+
* `__SHIM_CONFIG__` token and returns a self-contained string suitable for
|
|
11
|
+
* `Page.addInitScript` / `BROWSER eval` / a MAIN-world content script.
|
|
12
|
+
*
|
|
13
|
+
* This file is the runtime template — keep it dependency-free and ES2017
|
|
14
|
+
* compatible (no `??`, `?.` for older browsers is fine — most dApps run in
|
|
15
|
+
* modern Chrome). It must NOT import anything.
|
|
16
|
+
*/
|
|
17
|
+
(function installWalletShim() {
|
|
18
|
+
if (window.__elizaWalletShimInstalled) return;
|
|
19
|
+
window.__elizaWalletShimInstalled = true;
|
|
20
|
+
|
|
21
|
+
/** @type {{ apiBase: string, signToken: string, walletName: string, walletIcon: string, solanaPublicKey: string|null, evmAddress: string|null, evmChainId: number }} */
|
|
22
|
+
// The comment marker below is the substitution point used by build-shim.ts
|
|
23
|
+
// — keep it unique so the doc-block reference at the top of the file is
|
|
24
|
+
// never accidentally replaced first.
|
|
25
|
+
var CONFIG = /*ELIZA_WALLET_SHIM_CONFIG_INSERT*/ null;
|
|
26
|
+
|
|
27
|
+
// ---------- helpers ----------------------------------------------------
|
|
28
|
+
|
|
29
|
+
function bytesToBase64(bytes) {
|
|
30
|
+
var bin = "";
|
|
31
|
+
var chunk = 0x8000;
|
|
32
|
+
for (var i = 0; i < bytes.length; i += chunk) {
|
|
33
|
+
bin += String.fromCharCode.apply(
|
|
34
|
+
null,
|
|
35
|
+
bytes.subarray ? bytes.subarray(i, i + chunk) : bytes.slice(i, i + chunk),
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return btoa(bin);
|
|
39
|
+
}
|
|
40
|
+
function base64ToBytes(b64) {
|
|
41
|
+
var bin = atob(b64);
|
|
42
|
+
var out = new Uint8Array(bin.length);
|
|
43
|
+
for (var i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
function bytesToHex(bytes) {
|
|
47
|
+
var out = "0x";
|
|
48
|
+
for (var i = 0; i < bytes.length; i++) {
|
|
49
|
+
var h = bytes[i].toString(16);
|
|
50
|
+
out += h.length === 1 ? "0" + h : h;
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
function utf8ToBytes(s) {
|
|
55
|
+
return new TextEncoder().encode(s);
|
|
56
|
+
}
|
|
57
|
+
// base58 (Bitcoin alphabet) — small impl, only needed to log the active key
|
|
58
|
+
var B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
59
|
+
function base58Encode(bytes) {
|
|
60
|
+
var digits = [0];
|
|
61
|
+
for (var i = 0; i < bytes.length; i++) {
|
|
62
|
+
var carry = bytes[i];
|
|
63
|
+
for (var j = 0; j < digits.length; j++) {
|
|
64
|
+
carry += digits[j] << 8;
|
|
65
|
+
digits[j] = carry % 58;
|
|
66
|
+
carry = (carry / 58) | 0;
|
|
67
|
+
}
|
|
68
|
+
while (carry) {
|
|
69
|
+
digits.push(carry % 58);
|
|
70
|
+
carry = (carry / 58) | 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
var out = "";
|
|
74
|
+
for (var k = 0; k < bytes.length && bytes[k] === 0; k++) out += "1";
|
|
75
|
+
for (var m = digits.length - 1; m >= 0; m--) out += B58[digits[m]];
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
function base58Decode(s) {
|
|
79
|
+
var bytes = [0];
|
|
80
|
+
for (var i = 0; i < s.length; i++) {
|
|
81
|
+
var c = B58.indexOf(s[i]);
|
|
82
|
+
if (c < 0) throw new Error("invalid base58");
|
|
83
|
+
var carry = c;
|
|
84
|
+
for (var j = 0; j < bytes.length; j++) {
|
|
85
|
+
carry += bytes[j] * 58;
|
|
86
|
+
bytes[j] = carry & 0xff;
|
|
87
|
+
carry >>= 8;
|
|
88
|
+
}
|
|
89
|
+
while (carry) {
|
|
90
|
+
bytes.push(carry & 0xff);
|
|
91
|
+
carry >>= 8;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (var k = 0; k < s.length && s[k] === "1"; k++) bytes.push(0);
|
|
95
|
+
return new Uint8Array(bytes.reverse());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function api(path, body) {
|
|
99
|
+
return fetch(CONFIG.apiBase + path, {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: {
|
|
102
|
+
"Content-Type": "application/json",
|
|
103
|
+
Authorization: "Bearer " + CONFIG.signToken,
|
|
104
|
+
},
|
|
105
|
+
body: JSON.stringify(body || {}),
|
|
106
|
+
}).then(function (r) {
|
|
107
|
+
if (!r.ok) {
|
|
108
|
+
return r.text().then(function (t) {
|
|
109
|
+
throw new Error("wallet-shim " + path + " " + r.status + ": " + t);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return r.json();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---------- emitter ----------------------------------------------------
|
|
117
|
+
function makeEmitter() {
|
|
118
|
+
var listeners = {};
|
|
119
|
+
return {
|
|
120
|
+
on: function (e, l) {
|
|
121
|
+
(listeners[e] = listeners[e] || []).push(l);
|
|
122
|
+
return function () {
|
|
123
|
+
listeners[e] = (listeners[e] || []).filter(function (x) {
|
|
124
|
+
return x !== l;
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
emit: function (e) {
|
|
129
|
+
var args = [].slice.call(arguments, 1);
|
|
130
|
+
(listeners[e] || []).forEach(function (l) {
|
|
131
|
+
try {
|
|
132
|
+
l.apply(null, args);
|
|
133
|
+
} catch (_) {}
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ---------- Solana Wallet Standard -------------------------------------
|
|
140
|
+
function installSolana() {
|
|
141
|
+
if (!CONFIG.solanaPublicKey) return;
|
|
142
|
+
var publicKey = CONFIG.solanaPublicKey;
|
|
143
|
+
var publicKeyBytes = base58Decode(publicKey);
|
|
144
|
+
var emitter = makeEmitter();
|
|
145
|
+
|
|
146
|
+
var account = {
|
|
147
|
+
address: publicKey,
|
|
148
|
+
publicKey: publicKeyBytes,
|
|
149
|
+
chains: ["solana:mainnet", "solana:devnet", "solana:testnet"],
|
|
150
|
+
features: [
|
|
151
|
+
"solana:signTransaction",
|
|
152
|
+
"solana:signAndSendTransaction",
|
|
153
|
+
"solana:signMessage",
|
|
154
|
+
"standard:connect",
|
|
155
|
+
"standard:disconnect",
|
|
156
|
+
"standard:events",
|
|
157
|
+
],
|
|
158
|
+
label: CONFIG.walletName,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
function connect() {
|
|
162
|
+
return Promise.resolve({ accounts: [account] });
|
|
163
|
+
}
|
|
164
|
+
function disconnect() {
|
|
165
|
+
return Promise.resolve();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function signTransaction(input) {
|
|
169
|
+
var inputs = Array.isArray(input) ? input : [input];
|
|
170
|
+
var b64s = inputs.map(function (i) {
|
|
171
|
+
return bytesToBase64(i.transaction);
|
|
172
|
+
});
|
|
173
|
+
return api("/wallet/solana/sign-all-transactions", {
|
|
174
|
+
transactionsBase64: b64s,
|
|
175
|
+
}).then(function (resp) {
|
|
176
|
+
return resp.signedBase64s.map(function (b64) {
|
|
177
|
+
return { signedTransaction: base64ToBytes(b64) };
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function signAndSendTransaction(input) {
|
|
183
|
+
var inputs = Array.isArray(input) ? input : [input];
|
|
184
|
+
return Promise.all(
|
|
185
|
+
inputs.map(function (i) {
|
|
186
|
+
return api("/wallet/solana/sign-and-send-transaction", {
|
|
187
|
+
transactionBase64: bytesToBase64(i.transaction),
|
|
188
|
+
sendOptions: i.options || {},
|
|
189
|
+
}).then(function (resp) {
|
|
190
|
+
return { signature: base58Decode(resp.signature) };
|
|
191
|
+
});
|
|
192
|
+
}),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function signMessage(input) {
|
|
197
|
+
var inputs = Array.isArray(input) ? input : [input];
|
|
198
|
+
return Promise.all(
|
|
199
|
+
inputs.map(function (i) {
|
|
200
|
+
return api("/wallet/solana/sign-message", {
|
|
201
|
+
messageBase64: bytesToBase64(i.message),
|
|
202
|
+
}).then(function (resp) {
|
|
203
|
+
return {
|
|
204
|
+
signedMessage: i.message,
|
|
205
|
+
signature: base64ToBytes(resp.signatureBase64),
|
|
206
|
+
signatureType: "ed25519",
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
}),
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
var wallet = {
|
|
214
|
+
version: "1.0.0",
|
|
215
|
+
name: CONFIG.walletName,
|
|
216
|
+
icon: CONFIG.walletIcon,
|
|
217
|
+
chains: ["solana:mainnet", "solana:devnet", "solana:testnet"],
|
|
218
|
+
accounts: [account],
|
|
219
|
+
features: {
|
|
220
|
+
"standard:connect": { version: "1.0.0", connect: connect },
|
|
221
|
+
"standard:disconnect": { version: "1.0.0", disconnect: disconnect },
|
|
222
|
+
"standard:events": {
|
|
223
|
+
version: "1.0.0",
|
|
224
|
+
on: function (e, l) {
|
|
225
|
+
return emitter.on(e, l);
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
"solana:signTransaction": {
|
|
229
|
+
version: "1.0.0",
|
|
230
|
+
supportedTransactionVersions: ["legacy", 0],
|
|
231
|
+
signTransaction: signTransaction,
|
|
232
|
+
},
|
|
233
|
+
"solana:signAndSendTransaction": {
|
|
234
|
+
version: "1.0.0",
|
|
235
|
+
supportedTransactionVersions: ["legacy", 0],
|
|
236
|
+
signAndSendTransaction: signAndSendTransaction,
|
|
237
|
+
},
|
|
238
|
+
"solana:signMessage": {
|
|
239
|
+
version: "1.0.0",
|
|
240
|
+
signMessage: signMessage,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// --- Wallet Standard registration --------------------------------
|
|
246
|
+
function registerCallback(api) {
|
|
247
|
+
try {
|
|
248
|
+
api.register(wallet);
|
|
249
|
+
} catch (e) {
|
|
250
|
+
// already registered or registry refused — non-fatal
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function fireRegister() {
|
|
255
|
+
try {
|
|
256
|
+
var ev = new CustomEvent("wallet-standard:register-wallet", {
|
|
257
|
+
detail: registerCallback,
|
|
258
|
+
});
|
|
259
|
+
window.dispatchEvent(ev);
|
|
260
|
+
} catch (_) {}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Apps fire `wallet-standard:app-ready` with detail = api ({ register }).
|
|
264
|
+
try {
|
|
265
|
+
window.addEventListener(
|
|
266
|
+
"wallet-standard:app-ready",
|
|
267
|
+
function (e) {
|
|
268
|
+
if (e && e.detail) registerCallback(e.detail);
|
|
269
|
+
},
|
|
270
|
+
false,
|
|
271
|
+
);
|
|
272
|
+
} catch (_) {}
|
|
273
|
+
|
|
274
|
+
// We fire register-wallet immediately so app-side listeners see us.
|
|
275
|
+
fireRegister();
|
|
276
|
+
// And again on DOMContentLoaded + load to handle late wallet adapters.
|
|
277
|
+
if (document.readyState === "loading") {
|
|
278
|
+
document.addEventListener("DOMContentLoaded", fireRegister, false);
|
|
279
|
+
}
|
|
280
|
+
window.addEventListener("load", fireRegister, false);
|
|
281
|
+
|
|
282
|
+
// --- Phantom-compatibility legacy provider ----------------------
|
|
283
|
+
// Many older Solana dApps still detect `window.solana?.isPhantom`.
|
|
284
|
+
var phantomLike = {
|
|
285
|
+
isPhantom: true,
|
|
286
|
+
isConnected: true,
|
|
287
|
+
publicKey: { toBase58: function () { return publicKey; }, toBuffer: function () { return publicKeyBytes; }, toBytes: function () { return publicKeyBytes; }, toString: function () { return publicKey; } },
|
|
288
|
+
connect: function () {
|
|
289
|
+
return Promise.resolve({ publicKey: this.publicKey });
|
|
290
|
+
},
|
|
291
|
+
disconnect: function () {
|
|
292
|
+
emitter.emit("disconnect");
|
|
293
|
+
return Promise.resolve();
|
|
294
|
+
},
|
|
295
|
+
on: emitter.on,
|
|
296
|
+
off: function () {},
|
|
297
|
+
signTransaction: function (tx) {
|
|
298
|
+
// legacy phantom returns a single signed tx (Transaction object); we
|
|
299
|
+
// only have raw bytes so dApps using the new adapter pattern get the
|
|
300
|
+
// proper Wallet-Standard call instead.
|
|
301
|
+
var serialized =
|
|
302
|
+
typeof tx.serialize === "function"
|
|
303
|
+
? tx.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
304
|
+
: tx;
|
|
305
|
+
return api("/wallet/solana/sign-transaction", {
|
|
306
|
+
transactionBase64: bytesToBase64(new Uint8Array(serialized)),
|
|
307
|
+
}).then(function (resp) {
|
|
308
|
+
var bytes = base64ToBytes(resp.signedBase64);
|
|
309
|
+
// Try to populate signatures back into the original tx object so
|
|
310
|
+
// dApp code that does `tx.signatures` keeps working.
|
|
311
|
+
if (tx && Array.isArray(tx.signatures)) {
|
|
312
|
+
// No-op; we return raw bytes the dApp can re-deserialize.
|
|
313
|
+
}
|
|
314
|
+
// Most dApps either re-deserialize or call signAndSend; expose bytes
|
|
315
|
+
// via `serialize()` on the returned object.
|
|
316
|
+
return {
|
|
317
|
+
serialize: function () {
|
|
318
|
+
return bytes;
|
|
319
|
+
},
|
|
320
|
+
__signedBytes: bytes,
|
|
321
|
+
};
|
|
322
|
+
});
|
|
323
|
+
},
|
|
324
|
+
signAllTransactions: function (txs) {
|
|
325
|
+
var b64s = txs.map(function (tx) {
|
|
326
|
+
var serialized =
|
|
327
|
+
typeof tx.serialize === "function"
|
|
328
|
+
? tx.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
329
|
+
: tx;
|
|
330
|
+
return bytesToBase64(new Uint8Array(serialized));
|
|
331
|
+
});
|
|
332
|
+
return api("/wallet/solana/sign-all-transactions", {
|
|
333
|
+
transactionsBase64: b64s,
|
|
334
|
+
}).then(function (resp) {
|
|
335
|
+
return resp.signedBase64s.map(function (b64) {
|
|
336
|
+
var bytes = base64ToBytes(b64);
|
|
337
|
+
return {
|
|
338
|
+
serialize: function () {
|
|
339
|
+
return bytes;
|
|
340
|
+
},
|
|
341
|
+
__signedBytes: bytes,
|
|
342
|
+
};
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
signMessage: function (message, _encoding) {
|
|
347
|
+
return api("/wallet/solana/sign-message", {
|
|
348
|
+
messageBase64: bytesToBase64(
|
|
349
|
+
message instanceof Uint8Array ? message : utf8ToBytes(String(message)),
|
|
350
|
+
),
|
|
351
|
+
}).then(function (resp) {
|
|
352
|
+
return {
|
|
353
|
+
signature: base64ToBytes(resp.signatureBase64),
|
|
354
|
+
publicKey: { toBase58: function () { return publicKey; } },
|
|
355
|
+
};
|
|
356
|
+
});
|
|
357
|
+
},
|
|
358
|
+
signAndSendTransaction: function (tx, options) {
|
|
359
|
+
var serialized =
|
|
360
|
+
typeof tx.serialize === "function"
|
|
361
|
+
? tx.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
362
|
+
: tx;
|
|
363
|
+
return api("/wallet/solana/sign-and-send-transaction", {
|
|
364
|
+
transactionBase64: bytesToBase64(new Uint8Array(serialized)),
|
|
365
|
+
sendOptions: options || {},
|
|
366
|
+
}).then(function (resp) {
|
|
367
|
+
return { signature: resp.signature };
|
|
368
|
+
});
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
if (!window.solana) {
|
|
374
|
+
Object.defineProperty(window, "solana", {
|
|
375
|
+
value: phantomLike,
|
|
376
|
+
configurable: true,
|
|
377
|
+
writable: false,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
if (!window.phantom) {
|
|
381
|
+
Object.defineProperty(window, "phantom", {
|
|
382
|
+
value: { solana: phantomLike },
|
|
383
|
+
configurable: true,
|
|
384
|
+
writable: false,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
} catch (_) {}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// ---------- EIP-1193 / EIP-6963 EVM provider ---------------------------
|
|
391
|
+
function installEvm() {
|
|
392
|
+
if (!CONFIG.evmAddress) return;
|
|
393
|
+
var address = CONFIG.evmAddress.toLowerCase();
|
|
394
|
+
var emitter = makeEmitter();
|
|
395
|
+
var chainId = "0x" + CONFIG.evmChainId.toString(16);
|
|
396
|
+
|
|
397
|
+
function rpc(method, params) {
|
|
398
|
+
// Forward read-only RPC methods to a public RPC for this chain. The agent
|
|
399
|
+
// only signs; it does not proxy reads. The shim picks the chain-default
|
|
400
|
+
// RPC from the same map the server uses (see below).
|
|
401
|
+
return fetch(CONFIG.evmRpcByChainId[String(parseInt(chainId, 16))], {
|
|
402
|
+
method: "POST",
|
|
403
|
+
headers: { "Content-Type": "application/json" },
|
|
404
|
+
body: JSON.stringify({
|
|
405
|
+
jsonrpc: "2.0",
|
|
406
|
+
id: Date.now(),
|
|
407
|
+
method: method,
|
|
408
|
+
params: params || [],
|
|
409
|
+
}),
|
|
410
|
+
})
|
|
411
|
+
.then(function (r) {
|
|
412
|
+
return r.json();
|
|
413
|
+
})
|
|
414
|
+
.then(function (j) {
|
|
415
|
+
if (j.error) throw new Error(j.error.message || "rpc error");
|
|
416
|
+
return j.result;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
var provider = {
|
|
421
|
+
isMetaMask: true, // many dApps gate connect-button discovery on this
|
|
422
|
+
isElizaWallet: true,
|
|
423
|
+
_state: { isConnected: true, accounts: [address], chainId: chainId },
|
|
424
|
+
request: function (args) {
|
|
425
|
+
var method = args && args.method;
|
|
426
|
+
var params = (args && args.params) || [];
|
|
427
|
+
switch (method) {
|
|
428
|
+
case "eth_requestAccounts":
|
|
429
|
+
case "eth_accounts":
|
|
430
|
+
return Promise.resolve([address]);
|
|
431
|
+
case "eth_chainId":
|
|
432
|
+
case "net_version":
|
|
433
|
+
return Promise.resolve(
|
|
434
|
+
method === "net_version" ? String(parseInt(chainId, 16)) : chainId,
|
|
435
|
+
);
|
|
436
|
+
case "wallet_switchEthereumChain":
|
|
437
|
+
try {
|
|
438
|
+
var nextHex = params[0] && params[0].chainId;
|
|
439
|
+
if (typeof nextHex === "string") {
|
|
440
|
+
chainId = nextHex;
|
|
441
|
+
emitter.emit("chainChanged", chainId);
|
|
442
|
+
}
|
|
443
|
+
} catch (_) {}
|
|
444
|
+
return Promise.resolve(null);
|
|
445
|
+
case "wallet_addEthereumChain":
|
|
446
|
+
return Promise.resolve(null);
|
|
447
|
+
case "personal_sign": {
|
|
448
|
+
// params: [message, address] (some dApps reverse the order; tolerate both)
|
|
449
|
+
var msg = params[0];
|
|
450
|
+
var maybeAddr = params[1];
|
|
451
|
+
if (
|
|
452
|
+
typeof maybeAddr === "string" &&
|
|
453
|
+
maybeAddr.toLowerCase() !== address &&
|
|
454
|
+
typeof msg === "string" &&
|
|
455
|
+
msg.toLowerCase() === address
|
|
456
|
+
) {
|
|
457
|
+
var swap = msg;
|
|
458
|
+
msg = maybeAddr;
|
|
459
|
+
maybeAddr = swap;
|
|
460
|
+
}
|
|
461
|
+
return api("/wallet/evm/personal-sign", { message: msg }).then(
|
|
462
|
+
function (r) {
|
|
463
|
+
return r.signature;
|
|
464
|
+
},
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
case "eth_sign": {
|
|
468
|
+
return api("/wallet/evm/personal-sign", { message: params[1] }).then(
|
|
469
|
+
function (r) {
|
|
470
|
+
return r.signature;
|
|
471
|
+
},
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
case "eth_signTypedData_v4":
|
|
475
|
+
case "eth_signTypedData": {
|
|
476
|
+
var data = params[1];
|
|
477
|
+
if (typeof data === "string") {
|
|
478
|
+
try {
|
|
479
|
+
data = JSON.parse(data);
|
|
480
|
+
} catch (_) {}
|
|
481
|
+
}
|
|
482
|
+
return api("/wallet/evm/sign-typed-data", { typedData: data }).then(
|
|
483
|
+
function (r) {
|
|
484
|
+
return r.signature;
|
|
485
|
+
},
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
case "eth_sendTransaction": {
|
|
489
|
+
var tx = params[0] || {};
|
|
490
|
+
return api("/wallet/evm/send-transaction", {
|
|
491
|
+
chainId: parseInt(chainId, 16),
|
|
492
|
+
tx: tx,
|
|
493
|
+
}).then(function (r) {
|
|
494
|
+
return r.hash;
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
case "eth_signTransaction": {
|
|
498
|
+
var tx2 = params[0] || {};
|
|
499
|
+
return api("/wallet/evm/sign-transaction", {
|
|
500
|
+
chainId: parseInt(chainId, 16),
|
|
501
|
+
tx: tx2,
|
|
502
|
+
}).then(function (r) {
|
|
503
|
+
return r.signedTransaction;
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
default:
|
|
507
|
+
// forward read-only methods to public RPC
|
|
508
|
+
return rpc(method, params);
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
on: function (e, l) {
|
|
512
|
+
emitter.on(e, l);
|
|
513
|
+
},
|
|
514
|
+
removeListener: function () {},
|
|
515
|
+
enable: function () {
|
|
516
|
+
return Promise.resolve([address]);
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
try {
|
|
521
|
+
if (!window.ethereum) {
|
|
522
|
+
Object.defineProperty(window, "ethereum", {
|
|
523
|
+
value: provider,
|
|
524
|
+
configurable: true,
|
|
525
|
+
writable: false,
|
|
526
|
+
});
|
|
527
|
+
} else if (Array.isArray(window.ethereum.providers)) {
|
|
528
|
+
window.ethereum.providers.push(provider);
|
|
529
|
+
}
|
|
530
|
+
} catch (_) {}
|
|
531
|
+
|
|
532
|
+
// EIP-6963 — modern multi-wallet discovery used by RainbowKit, Wagmi, etc.
|
|
533
|
+
var info = {
|
|
534
|
+
uuid:
|
|
535
|
+
"00000000-0000-4000-8000-" +
|
|
536
|
+
("000000000000" + Math.floor(Math.random() * 1e12).toString(16)).slice(-12),
|
|
537
|
+
name: CONFIG.walletName,
|
|
538
|
+
icon: CONFIG.walletIcon,
|
|
539
|
+
rdns: "ai.elizaos.wallet",
|
|
540
|
+
};
|
|
541
|
+
function announce() {
|
|
542
|
+
try {
|
|
543
|
+
var ev = new CustomEvent("eip6963:announceProvider", {
|
|
544
|
+
detail: Object.freeze({ info: info, provider: provider }),
|
|
545
|
+
});
|
|
546
|
+
window.dispatchEvent(ev);
|
|
547
|
+
} catch (_) {}
|
|
548
|
+
}
|
|
549
|
+
try {
|
|
550
|
+
window.addEventListener("eip6963:requestProvider", announce, false);
|
|
551
|
+
} catch (_) {}
|
|
552
|
+
announce();
|
|
553
|
+
|
|
554
|
+
// Notify dApps that a connected wallet exists.
|
|
555
|
+
setTimeout(function () {
|
|
556
|
+
emitter.emit("connect", { chainId: chainId });
|
|
557
|
+
emitter.emit("accountsChanged", [address]);
|
|
558
|
+
}, 0);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
installSolana();
|
|
562
|
+
installEvm();
|
|
563
|
+
})();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
name: Publish Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- 1.x
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
verify_version:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
outputs:
|
|
13
|
+
should_publish: ${{ steps.check.outputs.should_publish }}
|
|
14
|
+
version: ${{ steps.check.outputs.version }}
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout repository
|
|
17
|
+
uses: actions/checkout@v6
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
|
|
21
|
+
- name: Check if package.json version changed
|
|
22
|
+
id: check
|
|
23
|
+
run: |
|
|
24
|
+
echo "Current branch: ${{ github.ref }}"
|
|
25
|
+
|
|
26
|
+
# Get current version
|
|
27
|
+
CURRENT_VERSION=$(jq -r .version package.json)
|
|
28
|
+
echo "Current version: $CURRENT_VERSION"
|
|
29
|
+
|
|
30
|
+
# Get previous commit hash
|
|
31
|
+
git rev-parse HEAD~1 || git rev-parse HEAD
|
|
32
|
+
PREV_COMMIT=$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD)
|
|
33
|
+
|
|
34
|
+
# Check if package.json changed
|
|
35
|
+
if git diff --name-only HEAD~1 HEAD | grep "package.json"; then
|
|
36
|
+
echo "Package.json was changed in this commit"
|
|
37
|
+
|
|
38
|
+
# Get previous version if possible
|
|
39
|
+
if git show "$PREV_COMMIT:package.json" 2>/dev/null; then
|
|
40
|
+
PREV_VERSION=$(git show "$PREV_COMMIT:package.json" | jq -r .version)
|
|
41
|
+
echo "Previous version: $PREV_VERSION"
|
|
42
|
+
|
|
43
|
+
if [ "$CURRENT_VERSION" != "$PREV_VERSION" ]; then
|
|
44
|
+
echo "Version changed from $PREV_VERSION to $CURRENT_VERSION"
|
|
45
|
+
echo "should_publish=true" >> $GITHUB_OUTPUT
|
|
46
|
+
else
|
|
47
|
+
echo "Version unchanged"
|
|
48
|
+
echo "should_publish=false" >> $GITHUB_OUTPUT
|
|
49
|
+
fi
|
|
50
|
+
else
|
|
51
|
+
echo "First commit with package.json, will publish"
|
|
52
|
+
echo "should_publish=true" >> $GITHUB_OUTPUT
|
|
53
|
+
fi
|
|
54
|
+
else
|
|
55
|
+
echo "Package.json not changed in this commit"
|
|
56
|
+
echo "should_publish=false" >> $GITHUB_OUTPUT
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
|
60
|
+
|
|
61
|
+
publish:
|
|
62
|
+
needs: verify_version
|
|
63
|
+
if: needs.verify_version.outputs.should_publish == 'true'
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
permissions:
|
|
66
|
+
contents: write
|
|
67
|
+
steps:
|
|
68
|
+
- name: Checkout repository
|
|
69
|
+
uses: actions/checkout@v6
|
|
70
|
+
with:
|
|
71
|
+
fetch-depth: 0
|
|
72
|
+
|
|
73
|
+
- name: Create Git tag
|
|
74
|
+
run: |
|
|
75
|
+
git config user.name "github-actions[bot]"
|
|
76
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
77
|
+
git tag -a "v${{ needs.verify_version.outputs.version }}" -m "Release v${{ needs.verify_version.outputs.version }}"
|
|
78
|
+
git push origin "v${{ needs.verify_version.outputs.version }}"
|
|
79
|
+
env:
|
|
80
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
81
|
+
|
|
82
|
+
- name: Setup Bun
|
|
83
|
+
uses: oven-sh/setup-bun@v2
|
|
84
|
+
|
|
85
|
+
- name: Install dependencies
|
|
86
|
+
run: bun install
|
|
87
|
+
|
|
88
|
+
- name: Build package
|
|
89
|
+
run: bun run build
|
|
90
|
+
|
|
91
|
+
- name: Publish to npm
|
|
92
|
+
run: bun publish
|
|
93
|
+
env:
|
|
94
|
+
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
95
|
+
|
|
96
|
+
create_release:
|
|
97
|
+
needs: [verify_version, publish]
|
|
98
|
+
if: needs.verify_version.outputs.should_publish == 'true'
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
permissions:
|
|
101
|
+
contents: write
|
|
102
|
+
steps:
|
|
103
|
+
- name: Create GitHub Release
|
|
104
|
+
uses: actions/create-release@v1
|
|
105
|
+
env:
|
|
106
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
107
|
+
with:
|
|
108
|
+
tag_name: "v${{ needs.verify_version.outputs.version }}"
|
|
109
|
+
release_name: "v${{ needs.verify_version.outputs.version }}"
|
|
110
|
+
body: "Release v${{ needs.verify_version.outputs.version }}"
|
|
111
|
+
draft: false
|
|
112
|
+
prerelease: false
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shaw Walters and elizaOS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|