@dvmkit/sdk 0.1.0-rc.4 → 0.1.0-rc.6
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/dist/{chunk-F2L6KIMD.js → chunk-5URG56JJ.js} +5 -143
- package/dist/{chunk-EDU6COY2.js → chunk-7AKBC4PW.js} +754 -150
- package/dist/chunk-ANFX5HEG.js +186 -0
- package/dist/{chunk-4UVRXDNY.js → chunk-CMDI3ENK.js} +342 -176
- package/dist/{chunk-GJD7PVWY.js → chunk-FJDCFHW5.js} +26 -12
- package/dist/{chunk-AAJNGQMC.js → chunk-JGGI65I3.js} +1 -1
- package/dist/{chunk-2K6UXDAN.js → chunk-KSQEFVFJ.js} +623 -691
- package/dist/{chunk-XYTSDAPH.js → chunk-LDTWX7JW.js} +1 -1
- package/dist/chunk-MKI6OVW4.js +194 -0
- package/dist/{chunk-AZBXSXQT.js → chunk-P4RUVDU7.js} +1 -0
- package/dist/chunk-TSWKITGR.js +772 -0
- package/dist/{credit-menu-ClA1JyYW.d.ts → credit-menu-CYkETVM4.d.ts} +22 -3
- package/dist/{fx-ptKVFOwq.d.ts → fx-Pf4Ey4f_.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/internal/index.d.ts +4974 -85
- package/dist/internal/index.js +3742 -167
- package/dist/{job-store-DxFqDPYq.d.ts → job-store-BtCaLnvJ.d.ts} +23 -1
- package/dist/server/index.d.ts +5 -5
- package/dist/server/index.js +8 -21
- package/dist/tempo-lifecycle-SQL3KLEZ.js +13 -0
- package/dist/tempo-wallet-QOLEIPCV.js +31 -0
- package/dist/testing/index.d.ts +1 -1
- package/dist/{usd-Cha_j80I.d.ts → usd-D7fW2S7I.d.ts} +1 -1
- package/dist/{x402-XXFQQAAD.js → x402-FTG2GRAQ.js} +6 -4
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isValidEvmPrivateKey,
|
|
3
|
+
loadConfig,
|
|
4
|
+
updateConfig
|
|
5
|
+
} from "./chunk-TSWKITGR.js";
|
|
6
|
+
import {
|
|
7
|
+
DvmError,
|
|
8
|
+
resolveRpcHttpTransportOptions,
|
|
9
|
+
resolveRpcOverride
|
|
10
|
+
} from "./chunk-MKI6OVW4.js";
|
|
11
|
+
import {
|
|
12
|
+
redactUrl,
|
|
13
|
+
redactUrlsInText
|
|
14
|
+
} from "./chunk-FUJ36YDV.js";
|
|
15
|
+
|
|
16
|
+
// src/lib/payment-rails/tempo-wallet.ts
|
|
17
|
+
var TEMPO_USDC_MAINNET = "0x20C000000000000000000000b9537d11c60E8b50";
|
|
18
|
+
var TEMPO_CHAIN_ID = 4217;
|
|
19
|
+
function resolveTempoAsset(env = process.env) {
|
|
20
|
+
const address = env.DVM_TEMPO_CURRENCY ?? TEMPO_USDC_MAINNET;
|
|
21
|
+
if (!HEX_ADDRESS_RE.test(address)) {
|
|
22
|
+
throw new DvmError(
|
|
23
|
+
"tempo_config_invalid",
|
|
24
|
+
`DVM_TEMPO_CURRENCY must be a 0x-prefixed 40-char hex address; got '${address}'.`,
|
|
25
|
+
"Unset DVM_TEMPO_CURRENCY to fall back to the bundled USDC.e mainnet default."
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
const symbol = tempoTokenSymbol(address);
|
|
29
|
+
return {
|
|
30
|
+
address,
|
|
31
|
+
symbol,
|
|
32
|
+
label: tempoTokenLabel(address),
|
|
33
|
+
unit: symbol ?? "tokens"
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function tempoTokenLabel(address) {
|
|
37
|
+
return tempoTokenSymbol(address) ?? `the token at ${shortAddress(address)}`;
|
|
38
|
+
}
|
|
39
|
+
function tempoTokenReference(address) {
|
|
40
|
+
const symbol = tempoTokenSymbol(address);
|
|
41
|
+
return symbol ? `${symbol} (${address})` : address;
|
|
42
|
+
}
|
|
43
|
+
function tempoBalanceCheckHint(token) {
|
|
44
|
+
const configured = tryResolveTempoAsset();
|
|
45
|
+
if (configured?.address.toLowerCase() === token.toLowerCase()) {
|
|
46
|
+
return "This channel's token is the rail's configured settlement asset, so 'dvm wallet balance' reads it.";
|
|
47
|
+
}
|
|
48
|
+
return `'dvm wallet balance' reads the rail's configured settlement asset (${configured?.address ?? "unresolvable in this environment"}) rather than this channel's token (${token}), so query that contract directly for the balance that matters here.`;
|
|
49
|
+
}
|
|
50
|
+
function tryResolveTempoAsset(env = process.env) {
|
|
51
|
+
try {
|
|
52
|
+
return resolveTempoAsset(env);
|
|
53
|
+
} catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function tempoWrongAssetHint(asset) {
|
|
58
|
+
return `This rail settles only in ${asset.label} (${asset.address}) on Tempo. Another Tempo dollar \u2014 USDT0 or any other stablecoin \u2014 is a different contract and will never show up here, however much of it your wallet says you hold. If you funded with the wrong one, swap it to ${asset.label} on Tempo (an on-chain swap, fees are sub-cent) or send ${asset.label} to this address.`;
|
|
59
|
+
}
|
|
60
|
+
function tempoTokenSymbol(address) {
|
|
61
|
+
return address.toLowerCase() === TEMPO_USDC_MAINNET.toLowerCase() ? "USDC.e" : null;
|
|
62
|
+
}
|
|
63
|
+
var HEX_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
64
|
+
async function connectedTempoAccount() {
|
|
65
|
+
const config = loadConfig();
|
|
66
|
+
return tempoAccountFromConfig(config);
|
|
67
|
+
}
|
|
68
|
+
async function generateTempoKey(opts = {}) {
|
|
69
|
+
const config = loadConfig();
|
|
70
|
+
if (!config) {
|
|
71
|
+
throw new DvmError(
|
|
72
|
+
"no_config",
|
|
73
|
+
"No config found.",
|
|
74
|
+
"Run `dvm init` before generating a Tempo wallet."
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
const existing = await tempoAccountFromConfig(config);
|
|
78
|
+
if (existing && !opts.force) {
|
|
79
|
+
throw new DvmError(
|
|
80
|
+
"tempo_wallet_exists",
|
|
81
|
+
`Tempo wallet already configured (address ${existing.address}).`,
|
|
82
|
+
"Pass `--force` to replace, or run `dvm wallet tempo-disconnect` to clear it first."
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
if (existing && opts.force) {
|
|
86
|
+
const { assertTempoWalletIdle } = await import("./tempo-lifecycle-SQL3KLEZ.js");
|
|
87
|
+
await assertTempoWalletIdle("replace");
|
|
88
|
+
}
|
|
89
|
+
const { privateKeyToAccount, generatePrivateKey } = await import("viem/accounts");
|
|
90
|
+
const privateKey = generatePrivateKey();
|
|
91
|
+
const account = privateKeyToAccount(privateKey);
|
|
92
|
+
const generated = {
|
|
93
|
+
privateKey,
|
|
94
|
+
address: account.address.toLowerCase()
|
|
95
|
+
};
|
|
96
|
+
await opts.beforePersist?.(generated);
|
|
97
|
+
await updateConfig({
|
|
98
|
+
reason: "tempo_wallet_generate",
|
|
99
|
+
patch: () => ({ set: { tempo: { method: "tempo", apiKey: privateKey } } })
|
|
100
|
+
});
|
|
101
|
+
return generated;
|
|
102
|
+
}
|
|
103
|
+
async function getTempoUsdcBalance(account) {
|
|
104
|
+
const tokenAddress = resolveTempoAsset().address;
|
|
105
|
+
const { createPublicClient, http, erc20Abi } = await import("viem");
|
|
106
|
+
const { tempo } = await import("viem/chains");
|
|
107
|
+
const { url: rpcUrl, source: rpcSource } = resolveRpcOverride(
|
|
108
|
+
process.env.DVM_TEMPO_RPC_URL,
|
|
109
|
+
tempo.rpcUrls.default.http[0]
|
|
110
|
+
);
|
|
111
|
+
try {
|
|
112
|
+
const transportOptions = resolveRpcHttpTransportOptions(
|
|
113
|
+
rpcSource,
|
|
114
|
+
process.env.DVM_TEMPO_RPC_HEADERS_JSON
|
|
115
|
+
);
|
|
116
|
+
const client = createPublicClient({
|
|
117
|
+
chain: tempo,
|
|
118
|
+
transport: transportOptions ? http(rpcUrl, transportOptions) : http(rpcUrl)
|
|
119
|
+
});
|
|
120
|
+
const raw = await client.readContract({
|
|
121
|
+
address: tokenAddress,
|
|
122
|
+
abi: erc20Abi,
|
|
123
|
+
functionName: "balanceOf",
|
|
124
|
+
args: [account.address]
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
address: account.address,
|
|
128
|
+
rawBaseUnits: raw,
|
|
129
|
+
usdc: Number(raw) / 1e6,
|
|
130
|
+
tokenAddress,
|
|
131
|
+
chainId: TEMPO_CHAIN_ID,
|
|
132
|
+
// internal-review: redacted here rather than at a display surface, so the clear
|
|
133
|
+
// endpoint never leaves this function on the success path either.
|
|
134
|
+
rpcUrlRedacted: redactUrl(rpcUrl),
|
|
135
|
+
rpcSource,
|
|
136
|
+
fetchedAtMs: Date.now()
|
|
137
|
+
};
|
|
138
|
+
} catch (err) {
|
|
139
|
+
const cause = redactUrlsInText(err instanceof Error ? err.message : String(err));
|
|
140
|
+
throw new DvmError(
|
|
141
|
+
"tempo_rpc_error",
|
|
142
|
+
`Tempo USDC balance lookup failed: ${cause}`,
|
|
143
|
+
// A caller who set the override doesn't need to be told to set it. Which
|
|
144
|
+
// knob is theirs to turn depends on whose endpoint this was.
|
|
145
|
+
rpcSource === "override" ? `DVM_TEMPO_RPC_URL sent this read to ${redactUrl(rpcUrl)}. Correct it, or unset it to fall back to Tempo's bundled endpoint.` : `Verify connectivity to Tempo's bundled endpoint (${redactUrl(rpcUrl)}), or send the read somewhere else with DVM_TEMPO_RPC_URL.`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async function deriveTempoAddress(privateKey) {
|
|
150
|
+
if (!isValidEvmPrivateKey(privateKey)) throw invalidTempoPrivateKey();
|
|
151
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
152
|
+
return privateKeyToAccount(privateKey).address.toLowerCase();
|
|
153
|
+
}
|
|
154
|
+
function shortAddress(addr) {
|
|
155
|
+
return `${addr.slice(0, 6)}\u2026${addr.slice(-4)}`;
|
|
156
|
+
}
|
|
157
|
+
async function tempoAccountFromConfig(config) {
|
|
158
|
+
if (config?.tempo?.method !== "tempo") return null;
|
|
159
|
+
const apiKey = config.tempo.apiKey;
|
|
160
|
+
if (!apiKey || !isValidEvmPrivateKey(apiKey)) return null;
|
|
161
|
+
const privateKey = apiKey;
|
|
162
|
+
const address = await deriveTempoAddress(privateKey);
|
|
163
|
+
return { privateKey, address };
|
|
164
|
+
}
|
|
165
|
+
function invalidTempoPrivateKey() {
|
|
166
|
+
return new DvmError(
|
|
167
|
+
"invalid_api_key",
|
|
168
|
+
"A Tempo private key must be a valid 0x-prefixed 32-byte hex secp256k1 private key.",
|
|
169
|
+
"Generate one with `cast wallet new` or `openssl rand -hex 32` (and prepend 0x)."
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export {
|
|
174
|
+
TEMPO_USDC_MAINNET,
|
|
175
|
+
TEMPO_CHAIN_ID,
|
|
176
|
+
resolveTempoAsset,
|
|
177
|
+
tempoTokenLabel,
|
|
178
|
+
tempoTokenReference,
|
|
179
|
+
tempoBalanceCheckHint,
|
|
180
|
+
tryResolveTempoAsset,
|
|
181
|
+
tempoWrongAssetHint,
|
|
182
|
+
connectedTempoAccount,
|
|
183
|
+
generateTempoKey,
|
|
184
|
+
getTempoUsdcBalance,
|
|
185
|
+
deriveTempoAddress
|
|
186
|
+
};
|