@c4roa0/agentpay-user 0.0.0-stage → 0.3.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/AGENTS.md +137 -0
- package/CONTRIBUTING.md +16 -0
- package/LICENSE +373 -0
- package/NOTICE.md +20 -0
- package/README.md +85 -2
- package/SECURITY.md +16 -0
- package/doc/README.md +52 -0
- package/doc/TODO.md +107 -0
- package/doc/architecture.md +99 -0
- package/doc/design.md +60 -0
- package/doc/develope.md +68 -0
- package/doc/plans/user-wallet-distribution.md +91 -0
- package/doc/reference/harness-skill-runtime.md +120 -0
- package/doc/reference/local-cache-foundation.md +176 -0
- package/doc/reference/local-safe-owner-ui.md +25 -0
- package/doc/reference/local-update.md +18 -0
- package/doc/reference/multi-service-runtime.md +119 -0
- package/doc/reference/npm-integration-verification.md +103 -0
- package/doc/reference/onboarding-writing.md +48 -0
- package/doc/reference/original-order-recovery.md +97 -0
- package/doc/reference/private-anvil-onboarding-config.example.json +18 -0
- package/doc/reference/public-deployment-settings.md +56 -0
- package/doc/reference/random-skill-contract.md +18 -0
- package/doc/reference/result-file-cache.md +166 -0
- package/doc/reference/runtime-address-recovery.md +42 -0
- package/doc/reference/runtime-result-cache.md +157 -0
- package/doc/reference/runtime-startup-recovery.md +141 -0
- package/doc/reference/skill-input-output-cache.md +93 -0
- package/doc/reference/wallet-identity-policy-history.md +23 -0
- package/doc/runbooks/commands.md +103 -0
- package/doc/runbooks/deployment-authorization-update.md +42 -0
- package/doc/runbooks/emergency-payment-stop.md +80 -0
- package/doc/runbooks/local-autostart.md +212 -0
- package/doc/runbooks/local-cache.md +115 -0
- package/doc/runbooks/local-update.md +84 -0
- package/doc/runbooks/market-connection.md +73 -0
- package/doc/runbooks/npm-publication.md +56 -0
- package/doc/runbooks/official-test-package.md +62 -0
- package/doc/runbooks/order-cancellation.md +56 -0
- package/doc/runbooks/order-support.md +41 -0
- package/doc/runbooks/policy-renewal.md +80 -0
- package/doc/runbooks/private-anvil-terminal-setup.md +58 -0
- package/doc/runbooks/runtime-skill-client.md +155 -0
- package/doc/runbooks/safe-owner-web.md +104 -0
- package/doc/runbooks/safe-policy-migration.md +36 -0
- package/doc/runbooks/safe-policy-setup.md +52 -0
- package/doc/runbooks/terminal-authorization-preview.md +38 -0
- package/doc/runbooks/unlock-wallet.md +68 -0
- package/doc/runbooks/user-onboarding.md +87 -0
- package/doc/runbooks/wallet-identity.md +59 -0
- package/doc/security/public-source-review-2026-11-06.md +71 -0
- package/doc/usage.md +54 -0
- package/package.json +49 -4
- package/progress.md +210 -0
- package/run +29 -0
- package/scripts/agentpay-cli.mjs +11 -0
- package/scripts/authorize-existing-safe.mjs +211 -0
- package/scripts/autostart.mjs +186 -0
- package/scripts/cancel-order.mjs +76 -0
- package/scripts/check-installation.mjs +26 -0
- package/scripts/check-official-test-package.mjs +35 -0
- package/scripts/check-purchase-readiness.mjs +275 -0
- package/scripts/configure-runtime-client.mjs +16 -0
- package/scripts/guide-policy.mjs +64 -0
- package/scripts/initialize-caller-credential.mjs +11 -0
- package/scripts/install-skill-bundle.mjs +176 -0
- package/scripts/install-user.mjs +24 -0
- package/scripts/local-service.mjs +60 -0
- package/scripts/lock.mjs +11 -0
- package/scripts/login-notify.mjs +39 -0
- package/scripts/migrate-safe-policy.mjs +165 -0
- package/scripts/official-paid-test.mjs +9 -0
- package/scripts/poll-unconfirmed-notice.mjs +75 -0
- package/scripts/prepare-onboarding.mjs +33 -0
- package/scripts/preview-policy.mjs +65 -0
- package/scripts/random-model-ack-smoke.mjs +235 -0
- package/scripts/random-reject-smoke.mjs +147 -0
- package/scripts/renew.mjs +9 -0
- package/scripts/repair.mjs +10 -0
- package/scripts/revoke.mjs +9 -0
- package/scripts/select-skill-bundle.mjs +39 -0
- package/scripts/setup-local.mjs +199 -0
- package/scripts/status.mjs +13 -0
- package/scripts/test-package.mjs +35 -0
- package/scripts/unlock.mjs +13 -0
- package/scripts/update.mjs +7 -0
- package/scripts/user-setup.mjs +219 -0
- package/scripts/verify-npm-release.mjs +32 -0
- package/src/active-skill.mjs +160 -0
- package/src/anvil-onboarding-state.mjs +96 -0
- package/src/anvil-onboarding.mjs +1036 -0
- package/src/authorization-question-checkpoint.mjs +114 -0
- package/src/autostart-files.mjs +50 -0
- package/src/cache-management-cli.mjs +302 -0
- package/src/cache-management.mjs +47 -0
- package/src/caller-auth.mjs +58 -0
- package/src/client-request-lock.mjs +44 -0
- package/src/connect-market.mjs +408 -0
- package/src/demo-unlock-secret.mjs +64 -0
- package/src/deployment-status.mjs +198 -0
- package/src/file-cache-cli.mjs +83 -0
- package/src/file-cache-owner.mjs +74 -0
- package/src/file-cache-settings.mjs +50 -0
- package/src/file-cache.mjs +790 -0
- package/src/file-download.mjs +281 -0
- package/src/finalization-disclosure.mjs +16 -0
- package/src/guided-setup.mjs +194 -0
- package/src/index.mjs +1233 -0
- package/src/install-and-setup.mjs +38 -0
- package/src/install-preflight.mjs +201 -0
- package/src/install-user.mjs +279 -0
- package/src/installation-paths.mjs +31 -0
- package/src/invocation-result.mjs +148 -0
- package/src/invocation-store.mjs +385 -0
- package/src/local-data-directory.mjs +117 -0
- package/src/local-info.mjs +181 -0
- package/src/local-services.mjs +156 -0
- package/src/local-time.mjs +36 -0
- package/src/local-update.mjs +316 -0
- package/src/local-wallet-ipc.mjs +93 -0
- package/src/login-reminder.mjs +28 -0
- package/src/market-download-url.mjs +21 -0
- package/src/node-version.mjs +12 -0
- package/src/npm-update.mjs +126 -0
- package/src/official-paid-test.mjs +407 -0
- package/src/official-test-package.mjs +41 -0
- package/src/official-test-update.mjs +162 -0
- package/src/order-cancellation.mjs +241 -0
- package/src/order-closure.mjs +42 -0
- package/src/order-list-panel.mjs +110 -0
- package/src/order-review.mjs +424 -0
- package/src/order-status-panel.mjs +65 -0
- package/src/order-support.mjs +365 -0
- package/src/owner-approval-server.mjs +332 -0
- package/src/owner-signer.mjs +67 -0
- package/src/policy-info.mjs +38 -0
- package/src/policy-migration.mjs +84 -0
- package/src/policy-operations.mjs +67 -0
- package/src/policy-preview-server.mjs +236 -0
- package/src/policy-terminal-guide.mjs +377 -0
- package/src/prepare-local-services.mjs +143 -0
- package/src/prepare-onboarding.mjs +210 -0
- package/src/private-journal-files.mjs +29 -0
- package/src/protocol-package.mjs +25 -0
- package/src/readiness-profile.mjs +30 -0
- package/src/renew-policy.mjs +605 -0
- package/src/repair-market-wallet.mjs +137 -0
- package/src/restore-wallet.mjs +255 -0
- package/src/result-cache-view.mjs +276 -0
- package/src/runtime-client.mjs +1145 -0
- package/src/runtime-connection-settings.mjs +101 -0
- package/src/runtime-recovery.mjs +667 -0
- package/src/runtime-status.mjs +32 -0
- package/src/safe-owner-anvil.mjs +115 -0
- package/src/safe-policy-plan.mjs +195 -0
- package/src/service-reference.mjs +233 -0
- package/src/service-url.mjs +52 -0
- package/src/settlement-response.mjs +69 -0
- package/src/setup-autostart.mjs +197 -0
- package/src/setup-demo.mjs +152 -0
- package/src/skill-bundle.mjs +142 -0
- package/src/skill-client.mjs +198 -0
- package/src/skill-install-prompt.mjs +31 -0
- package/src/skill-package.mjs +50 -0
- package/src/skill-zip.mjs +220 -0
- package/src/software-versions.mjs +48 -0
- package/src/status-panel.mjs +603 -0
- package/src/transport.mjs +48 -0
- package/src/uninstall-local.mjs +299 -0
- package/src/user-cli.mjs +354 -0
- package/src/user-setup-guide.mjs +193 -0
- package/src/wallet-control.mjs +182 -0
- package/src/wallet-ipc-error.mjs +16 -0
- package/src/wallet-package.mjs +28 -0
- package/update-pair.json +6 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
3
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
4
|
+
import { getAddress } from "ethers";
|
|
5
|
+
import { readFile, open, unlink } from "node:fs/promises";
|
|
6
|
+
const fields = [
|
|
7
|
+
"mode",
|
|
8
|
+
"chainId",
|
|
9
|
+
"source",
|
|
10
|
+
"rpcUrl",
|
|
11
|
+
"module",
|
|
12
|
+
"token",
|
|
13
|
+
"factory",
|
|
14
|
+
"registry",
|
|
15
|
+
"tokenDecimals",
|
|
16
|
+
"tokenSymbol",
|
|
17
|
+
"settlementUrl",
|
|
18
|
+
"marketBundleMetadataUrl",
|
|
19
|
+
"bundleSha256",
|
|
20
|
+
"maxUsageUnits",
|
|
21
|
+
];
|
|
22
|
+
export function validatePublicDeployment(input) {
|
|
23
|
+
if (
|
|
24
|
+
!input ||
|
|
25
|
+
typeof input !== "object" ||
|
|
26
|
+
Array.isArray(input) ||
|
|
27
|
+
Object.keys(input).some((key) => !fields.includes(key))
|
|
28
|
+
)
|
|
29
|
+
throw Error(
|
|
30
|
+
"Use the public User deployment file from Market; it must not contain participant data.",
|
|
31
|
+
);
|
|
32
|
+
if (
|
|
33
|
+
!["private-anvil", "production"].includes(input.mode) ||
|
|
34
|
+
!Number.isSafeInteger(input.chainId) ||
|
|
35
|
+
input.chainId < 1
|
|
36
|
+
)
|
|
37
|
+
throw Error("Invalid deployment mode or chain ID.");
|
|
38
|
+
for (const key of ["rpcUrl", "settlementUrl", "marketBundleMetadataUrl"]) {
|
|
39
|
+
const u = new URL(input[key]);
|
|
40
|
+
if (
|
|
41
|
+
!(
|
|
42
|
+
u.protocol === "https:" ||
|
|
43
|
+
(u.protocol === "http:" &&
|
|
44
|
+
["localhost", "127.0.0.1", "[::1]"].includes(u.hostname))
|
|
45
|
+
) ||
|
|
46
|
+
u.username ||
|
|
47
|
+
u.password ||
|
|
48
|
+
u.search ||
|
|
49
|
+
u.hash
|
|
50
|
+
)
|
|
51
|
+
throw Error("Deployment URLs require HTTPS or loopback HTTP.");
|
|
52
|
+
if (
|
|
53
|
+
key === "marketBundleMetadataUrl" &&
|
|
54
|
+
!/^\/(?:market\/)?skills\/bundles\/[^/]+\/metadata$/.test(u.pathname)
|
|
55
|
+
)
|
|
56
|
+
throw Error("Invalid test package URL.");
|
|
57
|
+
}
|
|
58
|
+
for (const key of ["module", "token", "factory", "registry"])
|
|
59
|
+
if (getAddress(input[key]) === "0x" + "0".repeat(40))
|
|
60
|
+
throw Error("Invalid contract address.");
|
|
61
|
+
if (
|
|
62
|
+
!Number.isInteger(input.tokenDecimals) ||
|
|
63
|
+
input.tokenDecimals < 0 ||
|
|
64
|
+
input.tokenDecimals > 36 ||
|
|
65
|
+
typeof input.tokenSymbol !== "string" ||
|
|
66
|
+
!/^[A-Za-z0-9_-]{1,20}$/.test(input.tokenSymbol) ||
|
|
67
|
+
!/^[a-f0-9]{64}$/.test(input.bundleSha256) ||
|
|
68
|
+
input.maxUsageUnits !== 1 ||
|
|
69
|
+
typeof input.source !== "string" ||
|
|
70
|
+
!input.source.trim()
|
|
71
|
+
)
|
|
72
|
+
throw Error("Invalid token or test package settings.");
|
|
73
|
+
return Object.fromEntries(fields.map((key) => [key, input[key]]));
|
|
74
|
+
}
|
|
75
|
+
export async function prepareOnboarding({
|
|
76
|
+
inputPath,
|
|
77
|
+
outputPath,
|
|
78
|
+
ask,
|
|
79
|
+
write,
|
|
80
|
+
continueAutomatically = false,
|
|
81
|
+
}) {
|
|
82
|
+
const raw = await readFile(inputPath);
|
|
83
|
+
if (raw.length > 16384) throw Error("Deployment file is too large.");
|
|
84
|
+
const deployment = validatePublicDeployment(JSON.parse(raw.toString("utf8")));
|
|
85
|
+
// Exclusive creation also rejects a symlink or existing participant configuration.
|
|
86
|
+
const file = await open(outputPath, "wx", 0o600);
|
|
87
|
+
let saved = false;
|
|
88
|
+
try {
|
|
89
|
+
const section = (title) =>
|
|
90
|
+
write(
|
|
91
|
+
`\n------------------------------------------------------------\n> ${title}\n------------------------------------------------------------`,
|
|
92
|
+
);
|
|
93
|
+
section("Local settings");
|
|
94
|
+
write(
|
|
95
|
+
`Network: eip155:${deployment.chainId}. Type 'q' at any input to cancel.`,
|
|
96
|
+
);
|
|
97
|
+
async function field(prompt, parse, error) {
|
|
98
|
+
for (;;) {
|
|
99
|
+
const value = (await ask(prompt)).trim();
|
|
100
|
+
if (value.toLowerCase() === "q")
|
|
101
|
+
throw Error("Cancelled; no configuration saved.");
|
|
102
|
+
try {
|
|
103
|
+
return parse(value);
|
|
104
|
+
} catch {
|
|
105
|
+
write(error);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const address = (value) => {
|
|
110
|
+
const result = getAddress(value);
|
|
111
|
+
if (result === "0x" + "0".repeat(40)) throw Error();
|
|
112
|
+
return result;
|
|
113
|
+
};
|
|
114
|
+
section("1/3 · Safe");
|
|
115
|
+
write(
|
|
116
|
+
"The Safe holds your purchase funds. Enter its account address on the network shown above.",
|
|
117
|
+
);
|
|
118
|
+
const safe = await field(
|
|
119
|
+
"Safe account address (0x…)",
|
|
120
|
+
address,
|
|
121
|
+
"Enter a valid Safe address: 0x followed by 40 hexadecimal characters.",
|
|
122
|
+
);
|
|
123
|
+
section("2/3 · Safe owner");
|
|
124
|
+
write(
|
|
125
|
+
"The owner is a wallet allowed to approve actions for the Safe. It has its own address.",
|
|
126
|
+
);
|
|
127
|
+
write(
|
|
128
|
+
"Enter a public address of one Safe owner. Approval still requires the configured Safe signature threshold.",
|
|
129
|
+
);
|
|
130
|
+
const ownerAddress = await field(
|
|
131
|
+
"Safe owner address (0x…)",
|
|
132
|
+
(value) => {
|
|
133
|
+
const a = address(value);
|
|
134
|
+
if (a === safe) throw Error();
|
|
135
|
+
return a;
|
|
136
|
+
},
|
|
137
|
+
"Enter a valid owner address, different from the Safe address.",
|
|
138
|
+
);
|
|
139
|
+
section("Owner approval");
|
|
140
|
+
write(
|
|
141
|
+
"Choose how to approve Safe operations. External uses your own wallet; anvil uses the prepared private test owner.",
|
|
142
|
+
);
|
|
143
|
+
const ownerSigner = await field(
|
|
144
|
+
"Owner signer: external or anvil (Enter for external)",
|
|
145
|
+
(v) => {
|
|
146
|
+
v = v || "external";
|
|
147
|
+
if (
|
|
148
|
+
!["external", "anvil"].includes(v) ||
|
|
149
|
+
(v === "anvil" &&
|
|
150
|
+
(deployment.chainId !== 31337 ||
|
|
151
|
+
new URL(deployment.rpcUrl).protocol !== "http:" ||
|
|
152
|
+
!["127.0.0.1", "localhost", "[::1]"].includes(
|
|
153
|
+
new URL(deployment.rpcUrl).hostname,
|
|
154
|
+
)))
|
|
155
|
+
)
|
|
156
|
+
throw Error();
|
|
157
|
+
return v;
|
|
158
|
+
},
|
|
159
|
+
"Enter external or anvil.",
|
|
160
|
+
);
|
|
161
|
+
section("3/3 · Local Runtime");
|
|
162
|
+
write(
|
|
163
|
+
"Your Agent connects to Runtime on this computer. Keep the default unless the port is already in use.",
|
|
164
|
+
);
|
|
165
|
+
const port = await field(
|
|
166
|
+
"Runtime port (press Enter for 6490)",
|
|
167
|
+
(value) => {
|
|
168
|
+
const n = Number(value || 6490);
|
|
169
|
+
if (
|
|
170
|
+
!/^\d+$/.test(value || "6490") ||
|
|
171
|
+
!Number.isInteger(n) ||
|
|
172
|
+
n < 1024 ||
|
|
173
|
+
n > 65535
|
|
174
|
+
)
|
|
175
|
+
throw Error();
|
|
176
|
+
return n;
|
|
177
|
+
},
|
|
178
|
+
"Enter a whole-number port from 1024 to 65535, or press Enter for 6490.",
|
|
179
|
+
);
|
|
180
|
+
section("Review local settings");
|
|
181
|
+
write(
|
|
182
|
+
`Safe: ${safe}\nOwner: ${ownerAddress}\nLocal Runtime: http://127.0.0.1:${port}`,
|
|
183
|
+
);
|
|
184
|
+
write("Saving these settings does not authorize spending.");
|
|
185
|
+
if (
|
|
186
|
+
(await ask("Type 'confirm' to save, or 'q' to cancel")).trim() !==
|
|
187
|
+
"confirm"
|
|
188
|
+
)
|
|
189
|
+
throw Error("Cancelled; no configuration saved.");
|
|
190
|
+
const config = {
|
|
191
|
+
...deployment,
|
|
192
|
+
safe,
|
|
193
|
+
ownerAddress,
|
|
194
|
+
ownerSigner,
|
|
195
|
+
runtimeUrl: `http://127.0.0.1:${port}`,
|
|
196
|
+
};
|
|
197
|
+
await file.writeFile(JSON.stringify(config, null, 2) + "\n");
|
|
198
|
+
await file.sync();
|
|
199
|
+
saved = true;
|
|
200
|
+
write(
|
|
201
|
+
continueAutomatically
|
|
202
|
+
? "Local settings saved. Continuing to Wallet setup."
|
|
203
|
+
: "Local settings saved. Continue with the setup command shown on the Market page. Wallet will verify the chain before authorization.",
|
|
204
|
+
);
|
|
205
|
+
return config;
|
|
206
|
+
} finally {
|
|
207
|
+
await file.close();
|
|
208
|
+
if (!saved) await unlink(outputPath);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
// User-owned migration journal storage; this module never reads Wallet keys.
|
|
3
|
+
import { lstat, mkdir, open, rename, unlink } from 'node:fs/promises';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
export async function assertPrivateFile(path) {
|
|
7
|
+
const info = await lstat(path);
|
|
8
|
+
if (!info.isFile() || info.isSymbolicLink() || info.uid !== process.getuid() || (info.mode & 0o077))
|
|
9
|
+
throw Object.assign(Error('User journal must be a private file owned by you.'), {code:'UNSAFE_FILE'});
|
|
10
|
+
}
|
|
11
|
+
export async function atomicWritePrivate(path, content) {
|
|
12
|
+
const parent = dirname(path);
|
|
13
|
+
await mkdir(parent, {recursive:true, mode:0o700});
|
|
14
|
+
const info = await lstat(parent);
|
|
15
|
+
if (!info.isDirectory() || info.isSymbolicLink() || info.uid !== process.getuid() || (info.mode & 0o077))
|
|
16
|
+
throw Error('User journal directory must be private and owned by you.');
|
|
17
|
+
const temporary = join(parent, '.tmp-' + randomUUID());
|
|
18
|
+
let handle;
|
|
19
|
+
try {
|
|
20
|
+
handle = await open(temporary, 'wx', 0o600);
|
|
21
|
+
await handle.writeFile(content, 'utf8');
|
|
22
|
+
await handle.sync();
|
|
23
|
+
await handle.close(); handle = null;
|
|
24
|
+
await rename(temporary, path);
|
|
25
|
+
} finally {
|
|
26
|
+
await handle?.close();
|
|
27
|
+
await unlink(temporary).catch(e => { if (e.code !== 'ENOENT') throw e; });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
// Resolve from each consumer independently: npm may install a nested Protocol copy.
|
|
7
|
+
// The public schema export works even when package.json is not publicly exported.
|
|
8
|
+
export function installedProtocol(consumerManifest) {
|
|
9
|
+
const require = createRequire(consumerManifest);
|
|
10
|
+
let directory = dirname(require.resolve('@c4roa0/agentpay-protocol/schema'));
|
|
11
|
+
for (;;) {
|
|
12
|
+
try {
|
|
13
|
+
const pkg = JSON.parse(readFileSync(join(directory, 'package.json'), 'utf8'));
|
|
14
|
+
if (pkg.name !== '@c4roa0/agentpay-protocol' || !/^\d+\.\d+\.\d+$/.test(pkg.version)) {
|
|
15
|
+
throw Error('Installed Protocol package identity is invalid.');
|
|
16
|
+
}
|
|
17
|
+
return pkg.version;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
if (error.code !== 'ENOENT') throw error;
|
|
20
|
+
}
|
|
21
|
+
const parent = dirname(directory);
|
|
22
|
+
if (parent === directory) throw Error('Installed Protocol package metadata is missing.');
|
|
23
|
+
directory = parent;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
3
|
+
// If a copy was not distributed with this file, see https://mozilla.org/MPL/2.0/.
|
|
4
|
+
const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
5
|
+
|
|
6
|
+
// Advisory only: actual Order preparation repeats these checks in Settlement.
|
|
7
|
+
export function settlementProfileBlocker(plan, profile) {
|
|
8
|
+
if (
|
|
9
|
+
!profile ||
|
|
10
|
+
!Number.isSafeInteger(profile.chainId) ||
|
|
11
|
+
typeof profile.network !== "string" ||
|
|
12
|
+
![
|
|
13
|
+
profile.assetAddress,
|
|
14
|
+
profile.factoryAddress,
|
|
15
|
+
profile.registryAddress,
|
|
16
|
+
].every((value) => typeof value === "string" && ADDRESS.test(value))
|
|
17
|
+
) {
|
|
18
|
+
return "SETTLEMENT_PROFILE_UNAVAILABLE";
|
|
19
|
+
}
|
|
20
|
+
if (
|
|
21
|
+
profile.chainId !== plan.chainId ||
|
|
22
|
+
profile.network !== `eip155:${plan.chainId}` ||
|
|
23
|
+
profile.assetAddress.toLowerCase() !== plan.token.toLowerCase() ||
|
|
24
|
+
profile.factoryAddress.toLowerCase() !== plan.factory.toLowerCase() ||
|
|
25
|
+
profile.registryAddress.toLowerCase() !== plan.registry.toLowerCase()
|
|
26
|
+
) {
|
|
27
|
+
return "POLICY_PROFILE_MISMATCH";
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|