@black-market/sdk 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -144
- package/assets/splash.png +0 -0
- package/dist/addresses.d.ts +3 -1
- package/dist/addresses.d.ts.map +1 -1
- package/dist/addresses.js +23 -17
- package/dist/addresses.js.map +1 -1
- package/dist/client.js +2 -2
- package/dist/client.js.map +1 -1
- package/dist/launch-api.d.ts +2 -1
- package/dist/launch-api.d.ts.map +1 -1
- package/dist/launch-api.js +2 -1
- package/dist/launch-api.js.map +1 -1
- package/dist/lifecycle/abi.d.ts +1246 -292
- package/dist/lifecycle/abi.d.ts.map +1 -1
- package/dist/lifecycle/abi.js +106 -12
- package/dist/lifecycle/abi.js.map +1 -1
- package/dist/lifecycle/progress.js +9 -9
- package/dist/lifecycle/progress.js.map +1 -1
- package/dist/lifecycle/schema.d.ts +3 -4
- package/dist/lifecycle/schema.d.ts.map +1 -1
- package/dist/lifecycle/schema.js +3 -4
- package/dist/lifecycle/schema.js.map +1 -1
- package/docs/launch-lifecycle.md +220 -41
- package/package.json +8 -3
- package/src/addresses.ts +25 -18
- package/src/client.ts +2 -2
- package/src/launch-api.ts +3 -2
- package/src/lifecycle/abi.ts +107 -12
- package/src/lifecycle/progress.ts +9 -9
- package/src/lifecycle/schema.ts +3 -4
package/docs/launch-lifecycle.md
CHANGED
|
@@ -2,42 +2,63 @@
|
|
|
2
2
|
|
|
3
3
|
`@black-market/sdk/lifecycle` is the browser-safe launch API; its exports are also available from `@black-market/sdk`. Supply the exact chain, core, creator and registry domain. Planning, salt preparation, reads and unsigned builders never sign, publish metadata or write to the source chain. A successful controlled-local simulation is not production deployment approval.
|
|
4
4
|
|
|
5
|
-
The canonical authorities are the registry/certification/adapter/config contracts under
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
`
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
`
|
|
36
|
-
`
|
|
37
|
-
|
|
38
|
-
`
|
|
39
|
-
`
|
|
40
|
-
|
|
5
|
+
The canonical authorities are the registry/certification/adapter/config contracts under
|
|
6
|
+
`contracts/src/launch/lifecycle/v2`, typed hook deployers, and `contracts/src/launch/fees/v3`
|
|
7
|
+
in the protocol repository. Plan identity is `LaunchPlanV1`. Pool-bound V4 uses **config 5**,
|
|
8
|
+
canonical Abyss uses **config 1**, and generic current shared-V4 support uses **config 4**.
|
|
9
|
+
|
|
10
|
+
## Deployed infrastructure
|
|
11
|
+
|
|
12
|
+
Robinhood mainnet (`4663`) selects the mined `pool-launch-v1` deployment captured at block
|
|
13
|
+
`80548181` in `contracts/deployments/launch/pool-launch-v1/20261005T053747Z-b5a7b88/manifest.json`.
|
|
14
|
+
The manifest records successful receipts and canonical runtime evidence. The graph has two
|
|
15
|
+
adapters and five admitted profiles: one fixed pool-bound V4 profile and four canonical Abyss
|
|
16
|
+
variants. It does not deploy a shared V4 root.
|
|
17
|
+
|
|
18
|
+
| SDK field | Mainnet address |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| `launchOrchestrator` | `0xb75CBD17b9aecb7305B4DFcDa69595F783341c0E` |
|
|
21
|
+
| `launchImplementationRegistry` | `0xaa8a410709B79cBA6F118F1be1FF568877A3B8Ee` |
|
|
22
|
+
| `launchFeeOwnerRegistry` | `0x15778Aad08e12D458B2848F035860e2a8c2a0725` |
|
|
23
|
+
|
|
24
|
+
`getAddresses(4663)` exposes this graph; `robinhoodLaunchApplication` exposes the mined
|
|
25
|
+
launch constants. Launch addresses on `31337` and `46631` remain zero unless configured.
|
|
26
|
+
Address overrides are evaluated once on import: bare names win, then `VITE_`, then
|
|
27
|
+
`NEXT_PUBLIC_`. Configure `LAUNCH_ORCHESTRATOR`, `LAUNCH_IMPLEMENTATION_REGISTRY`, and
|
|
28
|
+
`LAUNCH_FEE_OWNER_REGISTRY` from the same deployment evidence.
|
|
29
|
+
|
|
30
|
+
Canonical Abyss defaults are retained. DEX overrides apply on `31337` and `46631`, not
|
|
31
|
+
mainnet. Lending mainnet defaults use `contracts/deployments/robinhood/replacement-infrastructure.json`;
|
|
32
|
+
the workbench's existing lending endpoints follow that replacement. Lending overrides apply
|
|
33
|
+
on `31337` (all three prefixes) and `46631` (`VITE_`/`NEXT_PUBLIC_`); liquidation-executor
|
|
34
|
+
overrides use all three prefixes on every chain. Workbench chain RPC configuration reads
|
|
35
|
+
`VITE_RPC_URL`, then `NEXT_PUBLIC_RPC_URL`, then `RPC_URL`; client factories prefer their explicit
|
|
36
|
+
`rpcUrl`, then `RPC_URL`, then the chain endpoint. Select the chain explicitly in applications.
|
|
37
|
+
|
|
38
|
+
Registry V2 has one `LaunchCertificationV2` child. V4 uses `profileEnvelope`, `profileId`, and
|
|
39
|
+
signed six-argument `registerProfile`. Admin-only `registerAbyssProfile(uint8,registration)`
|
|
40
|
+
independently certifies config-1 variants without an author envelope or royalty allocation.
|
|
41
|
+
The admission EIP-712 domain is `Black Market Launch Registry`, version `2`.
|
|
42
|
+
|
|
43
|
+
`LaunchBoundsV2` has five members: minimum/maximum tick spacing, maximum positions,
|
|
44
|
+
maximum oracle cardinality, and fee-mode flags. Creators select valid LP/hook rates below
|
|
45
|
+
1,000,000 pips, a registered oracle configuration, and per-pool external-liquidity policy.
|
|
46
|
+
Author royalty ceilings are separate. Robinhood P1 `(1,4096)`, P2 `(6,4096)`, and P3 `(17,4096)`
|
|
47
|
+
can use the same admitted profile; the selected oracle is checked at the pinned block.
|
|
48
|
+
With `externalLiquidityDisabled=false`, third-party LP add/remove is allowed after opening.
|
|
49
|
+
Permanent launch custody and pre-opening protection still apply.
|
|
50
|
+
|
|
51
|
+
The deployed pool stack uses `FixedFeePoolHookV1`, `PoolHookDeployerV1`,
|
|
52
|
+
`PoolMarketAdapterV1`, and `PoolFeeCollectorFactoryV1`. The complete `fixedFeePoolHookV1Abi`
|
|
53
|
+
includes the exact **one-tuple, 18-field constructor**, callbacks, events, and errors from the
|
|
54
|
+
mined artifact. Its fixed scalar fee calculation does not imply a scalar-argument constructor.
|
|
55
|
+
Generic shared contracts are `FixedFeeSharedHookV1`, `SharedHookDeployerV1`, and
|
|
56
|
+
`SharedMarketAdapterV1`; they require their own admitted deployment graph.
|
|
57
|
+
Other current ABI exports include `sharedMarketAdapterV1Abi`, `sharedHookDeployerV1Abi`,
|
|
58
|
+
`poolMarketAdapterV1Abi`, `poolHookDeployerV1Abi`, and `poolFeeCollectorFactoryV1Abi`.
|
|
59
|
+
Validation uses `validateV4LifecycleMarket`; the collector factory getter is
|
|
60
|
+
`dependencyDigest(address)`. Identity domains are `black-market.launch-profile.v2`,
|
|
61
|
+
`black-market.v4-dependencies.v2`, and `black-market.pool-bound-market-economics.v1`.
|
|
41
62
|
|
|
42
63
|
## Public operations
|
|
43
64
|
|
|
@@ -108,13 +129,13 @@ Registry `authorizationDigest`, `beneficiaryNonces` and `registerProfile` ABIs e
|
|
|
108
129
|
(uint16,uint24,int24,uint160,uint24,uint8,uint8,address,bool,bytes32,bytes32,bytes32,bytes32,address,uint16,(int24,int24,uint128,bytes32,uint256)[])
|
|
109
130
|
```
|
|
110
131
|
|
|
111
|
-
Both preserve LP/hook fees, tick spacing, opening price, fee mode/denominator/treasury, external-liquidity policy and canonical oracle identity. Then come `profileId`, `termsDigest`, `developerBeneficiary
|
|
132
|
+
Both preserve LP/hook fees, tick spacing, opening price, fee mode/denominator/treasury, external-liquidity policy, and canonical oracle identity. Then come `profileId`, `termsDigest`, `developerBeneficiary`, and explicit `developerFeeBps`, followed by positions. Version 5 inserts `hookSalt` immediately before `profileId`. Every developer rate, including zero, is creator-selected. Copy terms from the selected profile's envelope. Inner/outer profile IDs must match; author identity is not the live payout. The creator rate cannot exceed either reviewed maximum or protocol ceiling.
|
|
112
133
|
|
|
113
134
|
```ts
|
|
114
135
|
const profile = profiles.find((row) => row.id === selectedProfileId);
|
|
115
136
|
if (!profile?.admitted || !profile.envelope || !profile.developerTerms) throw new Error("Selected profile is not reviewed/admitted");
|
|
116
|
-
const config =
|
|
117
|
-
version:
|
|
137
|
+
const config = encodePoolBoundV4LifecycleMarketConfig({
|
|
138
|
+
version: 5, hookSalt: zeroHash, lpFeePips, tickSpacing, sqrtPriceX96, hookFeePips, feeMode,
|
|
118
139
|
protocolFeeDenominator: profile.envelope.protocolFeeDenominator,
|
|
119
140
|
treasury: profile.envelope.protocolTreasury,
|
|
120
141
|
externalLiquidityDisabled: creatorSelectedExternalLiquidityDisabled,
|
|
@@ -238,6 +259,164 @@ Lifecycle dividend tokens retain independent current-owner dividend bounty up to
|
|
|
238
259
|
node examples/generate-lifecycle-commitment-fixture.mjs test/fixtures/launch-lifecycle-v1.json
|
|
239
260
|
```
|
|
240
261
|
|
|
241
|
-
|
|
262
|
+
Build and run the offline unit suite with `pnpm test`, and deployed read-only discovery with
|
|
263
|
+
`pnpm examples`. Unit regressions cover commitment/identity/numerical domains,
|
|
264
|
+
reviewed terms/rate/bounds, salt normalization/mining, receipt recovery, and author
|
|
265
|
+
authentication/routing/page outcomes. Wire vectors remain
|
|
266
|
+
offline schema references; they are not a mainnet launch or an admitted deployment graph.
|
|
267
|
+
|
|
268
|
+
`examples/launch.mjs` reviews a saved plan without signatures or source-chain writes:
|
|
269
|
+
|
|
270
|
+
```sh
|
|
271
|
+
pnpm build
|
|
272
|
+
node examples/launch.mjs --plan plan.json --rpc https://rpc.mainnet.chain.robinhood.com/ --mode staged --mine
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
The saved plan must use that RPC's chain and current deployment. `--mine` finalizes bound
|
|
276
|
+
salts offchain; `--limits current-limits.json`, `--receipts receipts.json`, and `--confirmations N`
|
|
277
|
+
supply explicit execution/recovery evidence. The command never invents provider/account limits.
|
|
278
|
+
Without a sequential simulation backend and matching execution-limit provenance, its review
|
|
279
|
+
can be provisional and cannot produce an admitted next transaction.
|
|
280
|
+
|
|
281
|
+
`examples/launch-lifecycle-smoke.mjs manifest.json sdk-plans.json` executes Solidity-exported
|
|
282
|
+
plans only on explicitly authorized owned loopback fixtures. It exercises atomic/staged
|
|
283
|
+
modes, typed predeployment, ordered buys, permanent custody, canonical recovery, no-argument
|
|
284
|
+
V3 harvest, and authenticated author claims. `test/lifecycle-chain.test.mjs` exercises
|
|
285
|
+
real-graph refusals/reorg/cancellation with the same fixture environment. See
|
|
286
|
+
[example instructions](../examples/README.md#actual-owned-fixture-proof) for the explicit
|
|
287
|
+
local-execution opt-in and required files.
|
|
288
|
+
|
|
289
|
+
## Individual token creation smoke
|
|
290
|
+
|
|
291
|
+
`pnpm smoke:launch` builds the SDK and runs `examples/smoke-launch.mjs` for **one**
|
|
292
|
+
case from an explicit `black-market.launch-smoke-fixture.v1` file. The
|
|
293
|
+
[shared local setup and eight case commands](../../black-market/docs/sdk-launch-smoke.md)
|
|
294
|
+
create separate owned loopback execution/simulation Anvil instances on chain `4663`
|
|
295
|
+
using the current deployed graph, not a replacement launcher. Use a real loopback
|
|
296
|
+
API with application storage and an indexer configured for that same execution chain.
|
|
297
|
+
No default live endpoint, private key, source-chain snapshot rollback or production
|
|
298
|
+
write is used. The older whole-suite Solidity-exported proof remains separate.
|
|
299
|
+
|
|
300
|
+
```sh
|
|
301
|
+
pnpm smoke:launch --help
|
|
302
|
+
pnpm smoke:launch --fixture /tmp/sdk-smoke/fixture.json --list
|
|
303
|
+
|
|
304
|
+
# Default plan-only: registry/provenance reads, token prediction and offchain salt mining.
|
|
305
|
+
pnpm smoke:launch --fixture /tmp/sdk-smoke/fixture.json \
|
|
306
|
+
--case erc20-staking-v4 --output /tmp/node-staking-plan
|
|
307
|
+
|
|
308
|
+
# Actual metadata signature/session, launch, custody/buy checks, publication and token GET.
|
|
309
|
+
pnpm smoke:launch --fixture /tmp/sdk-smoke/fixture.json \
|
|
310
|
+
--case erc20-staking-v4 --output /tmp/node-staking-launch \
|
|
311
|
+
--execute --api-url http://127.0.0.1:18763 --publish-timeout-seconds 90
|
|
312
|
+
|
|
313
|
+
# API omitted by explicit choice, not a full end-to-end pass.
|
|
314
|
+
pnpm smoke:launch --fixture /tmp/sdk-smoke/fixture.json \
|
|
315
|
+
--case erc404-abyss --output /tmp/node-erc404-chain --execute --chain-only
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
`--list` reads only the fixture catalogue, with no RPC, signature or write. A default
|
|
319
|
+
run persists the finalized portable `plan.json` and reports **“Plan prepared; launch
|
|
320
|
+
not executed”**, `scope: "plan-only"`, `execution: "not-run"` and API `not-run`.
|
|
321
|
+
Only `--execute` permits SDK `planLaunch`/controlled-fork simulation, metadata signing,
|
|
322
|
+
session creation and `eth_sendTransaction` from the fixture's unlocked Anvil creator.
|
|
323
|
+
Every endpoint must be an explicit loopback root and the fixture must declare
|
|
324
|
+
`fixtureOnly: true`; execution/simulation ports must differ. An API endpoint can come
|
|
325
|
+
from `fixture.apiUrl` or `--api-url`, never the production SDK default.
|
|
326
|
+
Local execution and instrumented simulation RPC HTTP calls have a bounded
|
|
327
|
+
120-second per-request timeout to accommodate cold nested-fork state reads; they
|
|
328
|
+
are not retried. API requests retain their separate timeout and publication deadline.
|
|
329
|
+
|
|
330
|
+
All eight cases cover ERC20/ERC404, staking/dividends, token-only burn, atomic/staged
|
|
331
|
+
execution, V4/Abyss/mixed markets and one through five permanent positions. Profiles
|
|
332
|
+
are registry-discovered: V4 must be admitted bound topology/config `5`; Abyss must be
|
|
333
|
+
the adapter's exact `profileId(3)` QUOTE_ORACLE/config `1`, not the first Abyss entry.
|
|
334
|
+
The runner uses exact frozen V4 treasury/denominator/author terms, explicit developer
|
|
335
|
+
rate `0`, measured local gas/calldata caps, current-block deadline and NativeWrap
|
|
336
|
+
funding. ERC20 supply is `1_000_000e18`; ERC404 supply is `10_000e18` with `100e18`
|
|
337
|
+
NFT units. It finalizes hook salts and saves the random identity before any write,
|
|
338
|
+
never switching mode, dropping positions/buys or changing economics to obtain admission.
|
|
339
|
+
|
|
340
|
+
Execution rechecks chain/creator/destination and exact finalized calldata before each
|
|
341
|
+
send. Submitted envelopes/hashes are persisted **before** receipt polling; included
|
|
342
|
+
receipts are preserved **before** status/provenance assertions and require one canonical
|
|
343
|
+
confirmation. Verification reads actual Active state, token runtime/name/symbol/factory
|
|
344
|
+
kind/reward binding, ERC404 unit/URI/mirror, canonical opened markets, permanent V4 sealed
|
|
345
|
+
custody/Abyss lock terms, fee policies and ordered activation buys.
|
|
346
|
+
|
|
347
|
+
The API session uses the SDK attribution schema with full EIP-712 domain and the same
|
|
348
|
+
name/symbol as the token, signed via owned Anvil `eth_signTypedData_v4`. Only the actual
|
|
349
|
+
atomic/activate transaction hash is published. Genuine `LaunchPublishPending` HTTP `202`
|
|
350
|
+
responses are polled within the configured deadline, respecting `Retry-After`; all other
|
|
351
|
+
errors fail immediately. Success additionally requires an actual optimistic/final session
|
|
352
|
+
matching that token/hash and an actual `/api/v1/launches/<token>?chainId=4663` representation
|
|
353
|
+
with matching creator, provenance and metadata. An API that cannot index `LaunchActivated`
|
|
354
|
+
must fail honestly; the runner does not manufacture projections or claim chain-only as
|
|
355
|
+
end-to-end success.
|
|
356
|
+
|
|
357
|
+
Every run requires a fresh exclusive `--output` directory (its parent must exist):
|
|
358
|
+
|
|
359
|
+
| Artifact | Evidence |
|
|
360
|
+
| --- | --- |
|
|
361
|
+
| `events.jsonl` | Timestamped SDK/case/stage events, RPC/API errors, simulation backend/steps/gas, timing and canonical observations. |
|
|
362
|
+
| `plan.json` | Full finalized SDK portable economic plan, written before execution. |
|
|
363
|
+
| `receipts.json` | Every submitted exact envelope/hash and subsequently observed receipt/reference, including failures. |
|
|
364
|
+
| `result.json` | `black-market.launch-smoke-result.v1`, scope, terminal passed/failed stage, chain/API observations, causal stacks and revert data. |
|
|
365
|
+
| `private-recovery.json` | Mode `0600`; the only file retaining API authorization signature and one-time capability. Do not share or commit it. |
|
|
366
|
+
|
|
367
|
+
Public artifacts recursively redact signatures, keys, capability/auth values and URL
|
|
368
|
+
credentials/query secrets while retaining public transaction calldata, hashes, selector
|
|
369
|
+
and revert bytes. Profile/draft/identity/planning/progress files provide additional
|
|
370
|
+
redacted context. Configuration, admission, transaction, publication and interruption
|
|
371
|
+
failures exit nonzero and preserve available evidence. The source chain is **not**
|
|
372
|
+
reverted, cancelled or relaunched after failure; only the SDK's separate simulation fork
|
|
373
|
+
restores its isolated simulation snapshots. Recover from stored evidence before deciding
|
|
374
|
+
to run a new case. Runner diagnostic unit tests are `test/smoke-launch.test.mjs`; they do
|
|
375
|
+
not replace actual fixture/API execution.
|
|
376
|
+
|
|
377
|
+
## Real HTTP API integration
|
|
378
|
+
|
|
379
|
+
The opt-in suites use `LaunchApiClient` and actual HTTP requests—not a mocked transport.
|
|
380
|
+
They do not start a service or provision storage. Configure an abyss-api service with:
|
|
381
|
+
|
|
382
|
+
- `/api/v1/launch-upload-sessions` and its capability-protected read route;
|
|
383
|
+
- real application PostgreSQL storage with launch-upload-session migrations applied;
|
|
384
|
+
- an enabled request chain matching `LAUNCH_API_TEST_CHAIN_ID`;
|
|
385
|
+
- its current launch verifying contract matching `LAUNCH_API_TEST_ORCHESTRATOR`.
|
|
386
|
+
|
|
387
|
+
For the actual abyss-api service, that verifying contract is the configured deployment
|
|
388
|
+
`contracts.launchFactory` field, which must contain the current orchestrator address.
|
|
389
|
+
The signed attribution domain is `Abyss Launch Attribution`, version `1`. Session signature
|
|
390
|
+
deadlines must be future timestamps at most 15 minutes away. Metadata hashes use canonical
|
|
391
|
+
NFC/trimmed text, normalized URLs, fixed field order, and null absent optional values.
|
|
392
|
+
|
|
393
|
+
| Environment | Meaning |
|
|
394
|
+
| --- | --- |
|
|
395
|
+
| `LAUNCH_API_TEST_URL` | Required HTTP service root, e.g. `http://127.0.0.1:18763`; no implicit production target. |
|
|
396
|
+
| `LAUNCH_API_TEST_CHAIN_ID` | Defaults to `4663`; must be configured on the test service. |
|
|
397
|
+
| `LAUNCH_API_TEST_ORCHESTRATOR` | Defaults to `0xb75CBD17b9aecb7305B4DFcDa69595F783341c0E`; must match the service's signing domain. |
|
|
398
|
+
| `LAUNCH_API_TEST_PRIVATE_KEY` | Required only for the explicit signed suite; disposable EOA key, never a production key. |
|
|
399
|
+
|
|
400
|
+
```sh
|
|
401
|
+
# Read-only capability/error boundaries; no key and no storage writes.
|
|
402
|
+
LAUNCH_API_TEST_URL=http://127.0.0.1:18763 pnpm test:api
|
|
403
|
+
|
|
404
|
+
# Signed metadata-session writes, allowed only on an owned disposable loopback service.
|
|
405
|
+
LAUNCH_API_TEST_URL=http://127.0.0.1:18763 \
|
|
406
|
+
LAUNCH_API_TEST_PRIVATE_KEY="$DISPOSABLE_TEST_PRIVATE_KEY" pnpm test:api:write
|
|
407
|
+
```
|
|
242
408
|
|
|
243
|
-
|
|
409
|
+
The write suite creates metadata-only sessions, reads persisted normalized metadata,
|
|
410
|
+
replays the byte-identical signed body without reissuing the one-time capability, refuses a
|
|
411
|
+
changed authorized payload under the same idempotency key, and checks capability isolation.
|
|
412
|
+
It also rejects wrong signers, wrong orchestrator/chain domains, altered metadata, a changed
|
|
413
|
+
idempotency key, expired authorization, and invalid signatures. The private key signs EIP-712
|
|
414
|
+
metadata only; it need not have a balance. Unique session/key/nonces permit repeat runs.
|
|
415
|
+
The disposable service operator owns database cleanup; the API has no session-deletion route.
|
|
416
|
+
|
|
417
|
+
Neither suite needs an image store, indexed launch, confirmed transaction hash, or chain
|
|
418
|
+
write. Metadata sessions do not prove token deployment, image publication, or transaction
|
|
419
|
+
indexing. Image/upload/publication operations require those additional real prerequisites
|
|
420
|
+
and are not exercised here. Explicitly selected suites fail on missing URL/key, absent
|
|
421
|
+
storage/routes, an unreachable service, or incompatible signing configuration instead of
|
|
422
|
+
silently skipping. Ordinary `pnpm test` stays offline and does not select HTTP integration.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@black-market/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Canonical TypeScript SDK for Black Market on Robinhood Chain (reviewed multi-market launches, Abyss DEX, lending).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"files": [
|
|
24
24
|
"dist",
|
|
25
25
|
"src",
|
|
26
|
-
"docs"
|
|
26
|
+
"docs",
|
|
27
|
+
"assets"
|
|
27
28
|
],
|
|
28
29
|
"sideEffects": false,
|
|
29
30
|
"engines": {
|
|
@@ -39,8 +40,12 @@
|
|
|
39
40
|
"dev": "tsc -p tsconfig.json --watch",
|
|
40
41
|
"examples": "pnpm build && node examples/quickstart.mjs",
|
|
41
42
|
"lint": "tsc -p tsconfig.json --noEmit",
|
|
43
|
+
"smoke:launch": "pnpm build && node examples/smoke-launch.mjs",
|
|
42
44
|
"prepublishOnly": "pnpm build",
|
|
43
|
-
"test": "pnpm
|
|
45
|
+
"test": "pnpm test:unit",
|
|
46
|
+
"test:unit": "pnpm build && node --test test/*.test.mjs",
|
|
47
|
+
"test:api": "pnpm build && node --test test/integration/launch-api.read.test.mjs",
|
|
48
|
+
"test:api:write": "pnpm build && node --test test/integration/launch-api.sessions.test.mjs",
|
|
44
49
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
45
50
|
},
|
|
46
51
|
"dependencies": {
|
package/src/addresses.ts
CHANGED
|
@@ -20,7 +20,7 @@ export type AbyssInfrastructureAddresses = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export type LaunchApplicationAddresses = {
|
|
23
|
-
/**
|
|
23
|
+
/** Mined mainnet deployment; local chains require explicit environment configuration. */
|
|
24
24
|
launchOrchestrator: Address;
|
|
25
25
|
launchImplementationRegistry: Address;
|
|
26
26
|
launchFeeOwnerRegistry: Address;
|
|
@@ -177,19 +177,26 @@ export const robinhoodAbyssInfrastructure: AbyssInfrastructureAddresses = {
|
|
|
177
177
|
abyssFeeRouter: "0x2c3B1b6fe0EDa8e10C0445567b47e66E825B34cd",
|
|
178
178
|
};
|
|
179
179
|
|
|
180
|
+
/** Mined pool-launch-v1 deployment, 20261005T053747Z-b5a7b88 (manifest.json). */
|
|
181
|
+
export const robinhoodLaunchApplication: LaunchApplicationAddresses = {
|
|
182
|
+
launchOrchestrator: "0xb75CBD17b9aecb7305B4DFcDa69595F783341c0E",
|
|
183
|
+
launchImplementationRegistry: "0xaa8a410709B79cBA6F118F1be1FF568877A3B8Ee",
|
|
184
|
+
launchFeeOwnerRegistry: "0x15778Aad08e12D458B2848F035860e2a8c2a0725",
|
|
185
|
+
};
|
|
186
|
+
|
|
180
187
|
|
|
181
|
-
/**
|
|
188
|
+
/** Robinhood-mainnet fork lending defaults; launch deployment remains explicit. */
|
|
182
189
|
const workbenchDefaults: ProtocolAddresses = {
|
|
183
190
|
...robinhoodAbyssInfrastructure,
|
|
184
191
|
...launchApplicationFromEnv(zeroLaunchApplication),
|
|
185
|
-
lendingPool: "
|
|
186
|
-
addressesProvider: "
|
|
187
|
-
dataProvider: "
|
|
192
|
+
lendingPool: "0x5D8878b145904425C598f12EB8eD550985369a82",
|
|
193
|
+
addressesProvider: "0x892faB533E8D04135D902F94974e45dB48C17697",
|
|
194
|
+
dataProvider: "0x1f3faA42C1D5cC330f6BD0242B9a56d611bdC78a",
|
|
188
195
|
uiPoolDataProvider: zero,
|
|
189
196
|
walletBalanceProvider: zero,
|
|
190
|
-
aaveOracle: "
|
|
197
|
+
aaveOracle: "0x6837B3cF5d959d01e07bf6DaB53f562877BF7d53",
|
|
191
198
|
liquidationExecutor: zero,
|
|
192
|
-
protocolVault: "
|
|
199
|
+
protocolVault: "0x83Ec5DbFEd6d972be89df88d3654EA2c70Fa2FB3",
|
|
193
200
|
ethUsdFeed: ROBINHOOD_ETH_USD,
|
|
194
201
|
weth: ROBINHOOD_WETH,
|
|
195
202
|
wethGateway: zero,
|
|
@@ -233,26 +240,26 @@ export const addresses: Record<SupportedChainId, ProtocolAddresses> = {
|
|
|
233
240
|
tokenVesting: envAddr(["TOKEN_VESTING", "VITE_TOKEN_VESTING", "NEXT_PUBLIC_TOKEN_VESTING"]),
|
|
234
241
|
faucet: envAddr(["FAUCET", "VITE_FAUCET", "NEXT_PUBLIC_FAUCET"]),
|
|
235
242
|
},
|
|
236
|
-
/**
|
|
243
|
+
/** Current mined launch, canonical Abyss, and replacement lending infrastructure. */
|
|
237
244
|
4663: {
|
|
238
245
|
...robinhoodAbyssInfrastructure,
|
|
239
|
-
...launchApplicationFromEnv(
|
|
240
|
-
lendingPool: "
|
|
241
|
-
addressesProvider: "
|
|
242
|
-
dataProvider: "
|
|
243
|
-
uiPoolDataProvider: "
|
|
244
|
-
walletBalanceProvider: "
|
|
245
|
-
aaveOracle: "
|
|
246
|
+
...launchApplicationFromEnv(robinhoodLaunchApplication),
|
|
247
|
+
lendingPool: "0x5D8878b145904425C598f12EB8eD550985369a82",
|
|
248
|
+
addressesProvider: "0x892faB533E8D04135D902F94974e45dB48C17697",
|
|
249
|
+
dataProvider: "0x1f3faA42C1D5cC330f6BD0242B9a56d611bdC78a",
|
|
250
|
+
uiPoolDataProvider: "0x02D2CA3bBbBaBD3C25bEDD4bE0eE6E5885C4D152",
|
|
251
|
+
walletBalanceProvider: "0xBbb5D81123C3d514456974e9Fe6C7C8d7a0E4E2A",
|
|
252
|
+
aaveOracle: "0x6837B3cF5d959d01e07bf6DaB53f562877BF7d53",
|
|
246
253
|
liquidationExecutor: envAddr([
|
|
247
254
|
"LIQUIDATION_EXECUTOR",
|
|
248
255
|
"VITE_LIQUIDATION_EXECUTOR",
|
|
249
256
|
"NEXT_PUBLIC_LIQUIDATION_EXECUTOR",
|
|
250
257
|
]),
|
|
251
|
-
protocolVault: "
|
|
258
|
+
protocolVault: "0x83Ec5DbFEd6d972be89df88d3654EA2c70Fa2FB3",
|
|
252
259
|
ethUsdFeed: ROBINHOOD_ETH_USD,
|
|
253
260
|
weth: ROBINHOOD_WETH,
|
|
254
|
-
wethGateway: "
|
|
255
|
-
lens: "
|
|
261
|
+
wethGateway: "0xa16aB7646267327cB26dD3533526309cDe676d9d",
|
|
262
|
+
lens: "0xB56079f966597CB9edaE27c589F8190f4dCD12df",
|
|
256
263
|
tokenVesting: zero,
|
|
257
264
|
faucet: zero,
|
|
258
265
|
},
|
package/src/client.ts
CHANGED
|
@@ -20,7 +20,7 @@ export function createProtocolPublicClient(opts?: {
|
|
|
20
20
|
}): PublicClient {
|
|
21
21
|
const chainId = opts?.chainId ?? 31337;
|
|
22
22
|
const chain = chains[chainId] ?? foundry;
|
|
23
|
-
const transport = http(opts?.rpcUrl ?? process.env.RPC_URL ??
|
|
23
|
+
const transport = http(opts?.rpcUrl ?? process.env.RPC_URL ?? chain.rpcUrls.default.http[0]);
|
|
24
24
|
return createPublicClient({ chain, transport });
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -31,7 +31,7 @@ export function createProtocolWalletClient(opts: {
|
|
|
31
31
|
}): WalletClient {
|
|
32
32
|
const chainId = opts.chainId ?? 31337;
|
|
33
33
|
const chain: Chain = chains[chainId] ?? foundry;
|
|
34
|
-
const transport: Transport = http(opts.rpcUrl ?? process.env.RPC_URL ??
|
|
34
|
+
const transport: Transport = http(opts.rpcUrl ?? process.env.RPC_URL ?? chain.rpcUrls.default.http[0]);
|
|
35
35
|
const account: Account = privateKeyToAccount(opts.privateKey);
|
|
36
36
|
return createWalletClient({ account, chain, transport });
|
|
37
37
|
}
|
package/src/launch-api.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type LaunchAttributionAuthorization = { nonce: Hex; deadline: string; sig
|
|
|
14
14
|
export type LaunchSessionCreateRequest = { chainId: number; wallet: Address; metadata: LaunchSessionCreateMetadata; image?: LaunchSessionImageDescriptor; authorization: LaunchAttributionAuthorization };
|
|
15
15
|
export type LaunchSessionPublishRequest = { chainId: number; transactionHash: Hash };
|
|
16
16
|
export type LaunchSessionStatus = "awaiting_upload" | "verifying_image" | "ready_to_launch" | "transaction_submitted" | "awaiting_indexer" | "optimistic" | "final" | "reorged" | "expired" | "rejected";
|
|
17
|
-
export type LaunchSessionDirectUpload = { url: string; headers: Record<string, string>;
|
|
17
|
+
export type LaunchSessionDirectUpload = { url: string; method: "PUT"; headers: Record<string, string>; expiresInSeconds: number };
|
|
18
18
|
export type LaunchSessionResponse = { sessionId: string; chainId: number; wallet: Address; status: LaunchSessionStatus; metadata: { name: string; symbol: string; description: string | null; websiteUrl: string | null; twitterUrl: string | null; telegramUrl: string | null; discordUrl: string | null }; image: { sha256: Hex; contentType: LaunchImageContentType; contentLength: number; width: number | null; height: number | null } | null; transactionHash?: Hash | null; token?: Address | null; canonicalStatus: "pending" | "optimistic" | "final" | "reorged"; metadataStatus: "queued" | "ready" | "needs_owner_action" | "none"; imageStatus: "none" | "upload_pending" | "verifying" | "ready" | "rejected"; retryable: boolean; createdAt: string; updatedAt: string; sessionExpiresAt: string; publishedAt?: string; upload?: LaunchSessionDirectUpload; capability?: string; imageUrl?: string };
|
|
19
19
|
export type LaunchApiErrorCode = "INVALID_REQUEST" | "INVALID_ADDRESS" | "INVALID_IDEMPOTENCY_KEY" | "INVALID_CAPABILITY" | "UNSUPPORTED_CHAIN" | "NOT_FOUND" | "IMAGE_INVALID" | "SESSION_STATE_CONFLICT" | "SESSION_EXPIRED" | "IDEMPOTENCY_CONFLICT" | "UPLOAD_CONFLICT" | "RATE_LIMITED" | "OVERLOADED" | "RPC_UNAVAILABLE" | "RPC_TIMEOUT" | "INDEXER_UNAVAILABLE" | "APP_STORAGE_UNAVAILABLE" | "IMAGE_STORAGE_UNAVAILABLE" | "TX_REVERTED" | "TX_PROVENANCE_MISMATCH" | "TX_METADATA_MISMATCH" | (string & {});
|
|
20
20
|
|
|
@@ -102,7 +102,8 @@ export const launchAttributionTypes = { LaunchAttribution: [
|
|
|
102
102
|
{ name: "idempotencyKey", type: "string" }, { name: "nonce", type: "bytes32" }, { name: "deadline", type: "uint256" },
|
|
103
103
|
] } as const;
|
|
104
104
|
export function canonicalLaunchMetadataHash(metadata: LaunchSessionMetadata): Hex {
|
|
105
|
-
|
|
105
|
+
const url = (value: string | undefined) => value === undefined ? null : new URL(value.normalize("NFC").trim()).toString();
|
|
106
|
+
return keccak256(stringToHex(JSON.stringify({ name: metadata.name.normalize("NFC").trim(), symbol: metadata.symbol.normalize("NFC").trim(), description: (metadata.description ?? "").normalize("NFC").trim(), websiteUrl: url(metadata.websiteUrl), twitterUrl: url(metadata.twitterUrl), telegramUrl: url(metadata.telegramUrl), discordUrl: url(metadata.discordUrl), imageKey: metadata.imageKey ?? null })));
|
|
106
107
|
}
|
|
107
108
|
export async function sha256Hex(bytes: ArrayBuffer): Promise<Hex> {
|
|
108
109
|
const digest = await crypto.subtle.digest("SHA-256", bytes);
|