@d20dao/vrf-sdk 0.1.1 → 0.1.2

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 CHANGED
@@ -1,43 +1,43 @@
1
- # d20dao consumer-agent guide
2
-
3
- Use this guide when integrating @d20dao/vrf-sdk into an application or interpreting its public evidence. Install with `npm install @d20dao/vrf-sdk`. The package provides a general randomness interface; dice and mining contracts are examples. Read installed declarations for exact types and match the packaged PROTOCOL-PROVENANCE.json to the deployment being used.
4
-
5
- ## Public interfaces
6
-
7
- Import builtins, mapRandomness, decodeEvidencePacket and replayCoordinator from @d20dao/vrf-sdk. Epoch helpers also have an /epoch entrypoint. Import coordinatorAbi and epochEntropyAbi from /abi. Solidity consumers use D20VRFConsumer, ID20VRF, D20VRFRequests and RandomnessMapping under /contracts with compiler 0.8.28.
8
-
9
- RequestContext binds chainId, effective coordinator proxy, keyHash, requestId, consumer, clientSeed, mapping, requestBlock, targetBlock, blockHash, epochId and epochHash. Consult Parameters<typeof replayCoordinator>[0] for the complete trusted replay input. configuration.feeRecipient uses the initialized initialFeeRecipient, not the current payout address.
10
-
11
- ## Request lifecycle
12
-
13
- Epochs last 200 blocks. The keeper prepares the first validated API3 snapshot locally using the source anchor at epochStart-1. Idle preparation causes no publication transaction. Unused snapshots may remain locally for 50 epochs/10,000 blocks, with live-request and unresolved-transaction protection.
14
-
15
- After activation, a consumer escrows the exact requestFee even if its epoch is unpublished. Live allowlisted demand triggers publication of that saved packet. The target becomes max(requestBlock,committedBlock+1); no usable VRF seed exists until that future hash is known. Preserve original request block, epoch, client seed, mapping, recipient and 60-second deadline. Older-epoch demand can settle across a boundary without changing its packet.
16
-
17
- Require exact payment and keep caller/request association stable. D20VRFConsumer authenticates the coordinator proxy; verify the expected request and store the raw callback word with minimal work. Mapped requests still callback with bytes32; use getMappedResult or canonical mapping. Keep application actions and payments separate from the callback.
18
-
19
- Valid onchain acceptance at or before requestedAt+60 seconds is timely. A pending transaction is not acceptance. Callback failure still earns service payment; retryCallback redelivers only the same accepted result. After expiry, an unfulfilled request refunds its fixed recipient or refund credit. Application-payment refunds are separate.
20
-
21
- Keeper share pays the configured registry committer, not an arbitrary proof submitter. Failed payment creates keeper credit. Refund escrow is separate, and retrying delivery cannot pay a second share.
22
-
23
- ## Verification and trust
24
-
25
- The four ordered recipe slots are Hyperliquid BTC volume, ANU, TickerLayer BTCUSD and TickerLayer ETHUSD; the latter two share a provider signer. Preserve the entire exact signed response, limited to 128 bytes. Signatures establish wrapper provenance, not unbiased upstream data.
26
-
27
- Decode epoch evidence using its trusted registry/event context and decodeEvidencePacket for FulfillmentEvidence. Proof evidence is 416 bytes; fulfillment calldata is 452 bytes. Supply independently trusted successful receipts, proxy implementation history, source/publication/request/target blocks and timestamps, initialized key/configuration and original signed packets. Compare both event and stored transcript commitments. Decoding and mapping alone do not verify origin; replay does not authenticate RPC or establish inclusion.
28
-
29
- Both service contracts use atomically initialized D20Proxy endpoints with owner-authorized UUPS upgrades and two-step ownership. Implementations are locked against initialization. Upgrade authority is trusted. Verify the implementation history of BOTH coordinator and registry; stable proxy addresses alone do not identify executed code. Operator pins stop processing on unreviewed changes while preserving recovery data.
30
-
31
- ## Service boundaries
32
-
33
- Always configure the actual chain explicitly; there is no implicit Arc network default. Obtain consumer onboarding and approved proxy/configuration details before live requests. Healthy process status does not guarantee a particular request's timely fulfillment.
34
-
35
- This SDK holds no signer or bot keys, runs no keeper/prover and exposes no operator API. Optional Telegram access is disabled by default and limited to read-only /status and /keeper in the configured operator chat. Those commands cannot alter configuration or send transactions. Docker provisioning, upgrades, funding and publishing are separate operator actions, not consequences of SDK integration.
36
-
37
- ## Optional refund notification
38
-
39
- A coordinator with refund-hook support calls `onRefund(requestId)` on the original consumer after the fee is paid to its fixed refund address or recorded as backed credit. Extend `D20VRFConsumer` and override `_onRefund(uint256 requestId)` to update application state; the base authenticates the coordinator. The callback only carries the request ID and does not imply that the consumer itself received money. Application assets and fees remain the application's responsibility.
40
-
41
- The first attempt forwards 100,000 gas. A reverting or gas-exhausting hook cannot undo the fee settlement. After failure, `retryRefundCallback(requestId, gasLimit)` retries the notification without another payment; successful delivery is recorded by `refundCallbackDelivered(requestId)`. Refund/retry needs sufficient outer gas. Never request new randomness from within either callback; use a separate application transaction.
42
-
1
+ # d20dao consumer-agent guide
2
+
3
+ Use this guide when integrating @d20dao/vrf-sdk into an application or interpreting its public evidence. Install with `npm install @d20dao/vrf-sdk`. The package provides a general randomness interface; dice and mining contracts are examples. Read installed declarations for exact types and match the packaged PROTOCOL-PROVENANCE.json to the deployment being used.
4
+
5
+ ## Public interfaces
6
+
7
+ Import builtins, mapRandomness, decodeEvidencePacket and replayCoordinator from @d20dao/vrf-sdk. Epoch helpers also have an /epoch entrypoint. Import coordinatorAbi and epochEntropyAbi from /abi. Solidity consumers use D20VRFConsumer, ID20VRF, D20VRFRequests and RandomnessMapping under /contracts with compiler 0.8.28.
8
+
9
+ RequestContext binds chainId, effective coordinator proxy, keyHash, requestId, consumer, clientSeed, mapping, requestBlock, targetBlock, blockHash, epochId and epochHash. Consult Parameters<typeof replayCoordinator>[0] for the complete trusted replay input. configuration.feeRecipient uses the initialized initialFeeRecipient, not the current payout address.
10
+
11
+ ## Request lifecycle
12
+
13
+ Epochs last 200 blocks. The keeper prepares the first validated API3 snapshot locally using the source anchor at epochStart-1. Idle preparation causes no publication transaction. Unused snapshots may remain locally for 50 epochs/10,000 blocks, with live-request and unresolved-transaction protection.
14
+
15
+ After activation, a consumer escrows the exact requestFee even if its epoch is unpublished. Live paid demand triggers publication of that saved packet. The target becomes max(requestBlock,committedBlock+1); no usable VRF seed exists until that future hash is known. Preserve original request block, epoch, client seed, mapping, recipient and 60-second deadline. Older-epoch demand can settle across a boundary without changing its packet.
16
+
17
+ Require exact payment and keep caller/request association stable. D20VRFConsumer authenticates the coordinator proxy; verify the expected request and store the raw callback word with minimal work. Mapped requests still callback with bytes32; use getMappedResult or canonical mapping. Keep application actions and payments separate from the callback.
18
+
19
+ Valid onchain acceptance at or before requestedAt+60 seconds is timely. A pending transaction is not acceptance. Callback failure still earns service payment; retryCallback redelivers only the same accepted result. After expiry, an unfulfilled request refunds its fixed recipient or refund credit. Application-payment refunds are separate.
20
+
21
+ Keeper share pays the configured registry committer, not an arbitrary proof submitter. Failed payment creates keeper credit. Refund escrow is separate, and retrying delivery cannot pay a second share.
22
+
23
+ ## Verification and trust
24
+
25
+ The four ordered recipe slots are Hyperliquid BTC volume, ANU, TickerLayer BTCUSD and TickerLayer ETHUSD; the latter two share a provider signer. Preserve the entire exact signed response, limited to 128 bytes. Signatures establish wrapper provenance, not unbiased upstream data.
26
+
27
+ Decode epoch evidence using its trusted registry/event context and decodeEvidencePacket for FulfillmentEvidence. Proof evidence is 416 bytes; fulfillment calldata is 452 bytes. Supply independently trusted successful receipts, proxy implementation history, source/publication/request/target blocks and timestamps, initialized key/configuration and original signed packets. Compare both event and stored transcript commitments. Decoding and mapping alone do not verify origin; replay does not authenticate RPC or establish inclusion.
28
+
29
+ Both service contracts use atomically initialized D20Proxy endpoints with owner-authorized UUPS upgrades and two-step ownership. Implementations are locked against initialization. Upgrade authority is trusted. Verify the implementation history of BOTH coordinator and registry; stable proxy addresses alone do not identify executed code. Operator pins stop processing on unreviewed changes while preserving recovery data.
30
+
31
+ ## Service boundaries
32
+
33
+ Always configure the actual chain explicitly; there is no implicit Arc network default. Use the correct public deployment proxy and configuration before live requests. Healthy process status does not guarantee a particular request's timely fulfillment.
34
+
35
+ This SDK holds no signer or bot keys, runs no keeper/prover and exposes no operator API. Optional Telegram access is disabled by default and limited to read-only /status and /keeper in the configured operator chat. Those commands cannot alter configuration or send transactions. Docker provisioning, upgrades, funding and publishing are separate operator actions, not consequences of SDK integration.
36
+
37
+ ## Optional refund notification
38
+
39
+ A coordinator with refund-hook support calls `onRefund(requestId)` on the original consumer after the fee is paid to its fixed refund address or recorded as backed credit. Extend `D20VRFConsumer` and override `_onRefund(uint256 requestId)` to update application state; the base authenticates the coordinator. The callback only carries the request ID and does not imply that the consumer itself received money. Application assets and fees remain the application's responsibility.
40
+
41
+ The first attempt forwards 100,000 gas. A reverting or gas-exhausting hook cannot undo the fee settlement. After failure, `retryRefundCallback(requestId, gasLimit)` retries the notification without another payment; successful delivery is recorded by `refundCallbackDelivered(requestId)`. Refund/retry needs sufficient outer gas. Never request new randomness from within either callback; use a separate application transaction.
42
+
43
43
  This SDK includes the new source interface. Installing it does not upgrade a deployed coordinator: verify the implementation and its refund-hook capability before relying on notification delivery.
@@ -26,7 +26,7 @@
26
26
  "contracts/D20Proxy.sol": "83dcef3b72e2a0a4809c2d8df0d083d2a0f659fe2b3b01fadb1b2eaf8afb7286"
27
27
  }
28
28
  },
29
- "packageLockSha256": "1d2bf6fb1edee2c71f9bccf589f5ef33921b873996129ed965fa982c58bd8c9c",
29
+ "packageLockSha256": "1040ab4287e77f250a4ea54fcb68f5ed3d29b61582c5e52d2f7d1e05136a4529",
30
30
  "buildDependencies": {
31
31
  "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": "41a3040398d53999dea3251ff8906e11ec1a699362a1d8f4a55bfc7709cc00f3",
32
32
  "@openzeppelin/contracts/utils/ReentrancyGuard.sol": "94e409e8f6e3184236651a6cc2b1a6a3ea0f0a25eb85b71e524ad5791bb2fbc8",
package/README.md CHANGED
@@ -1,99 +1,99 @@
1
- # d20dao VRF SDK
2
-
3
- Public replay, mapping, epoch evidence and Solidity consumer helpers for a general randomness service. Package: `@d20dao/vrf-sdk` `0.1.1`.
4
-
5
- ## Getting started
6
-
7
- ```sh
8
- npm install @d20dao/vrf-sdk
9
- ```
10
-
11
- Use Node 22.13 or newer and Solidity 0.8.28. Configure the coordinator proxy from the [current deployment manifest](https://github.com/d20dao/keeper/blob/main/deployments/arc-testnet.json), then follow the consumer example below. Arc Testnet is chain 5042002; arrange consumer allowlisting before live requests. Read `requestFee()` at runtime and keep application payments separate.
12
-
13
- For agent-assisted integration, give your agent the installed `AGENTS.md` and `PROTOCOL-PROVENANCE.json`, plus the [integration skills](https://github.com/d20dao/skills). Website guides include Getting started, Copy prompt, `/llms.txt`, `/llms-full.txt` and `/agents.md`.
14
-
15
- ## Current request flow
16
-
17
- Epochs last 200 blocks. The keeper selects one of four fixed recipes using the canonical block hash at epoch start minus one and prepares its first validated API3 snapshot locally. Idle preparation publishes no transaction. An unused local snapshot can be retained for 50 epochs (10,000 blocks), subject to live-demand and unresolved-transaction protection.
18
-
19
- After activation, a consumer escrows the exact request fee even when the epoch packet is not published. The request fixes its original block, epoch, client seed, mapping, recipient and 60-second deadline. The keeper publishes the saved packet only for live allowlisted demand. The randomness target becomes `max(requestBlock, committedBlock + 1)`, so its hash is unknown at publication. Before publication the request has no usable target or VRF seed. Multiple requests share the packet, and timely requests can settle across epoch boundaries without changing their epoch.
20
-
21
- The four ordered recipe slots are Hyperliquid BTC volume, ANU quantum data, TickerLayer BTCUSD lastTrade and TickerLayer ETHUSD lastTrade. Both TickerLayer slots use the same provider signer and crypto asset class. `EpochSigners` is a readonly four-address tuple. The full exact signed data is limited to 128 bytes and emitted publicly; do not crop or replace it. A signature establishes provider-wrapper provenance, not unbiased upstream data or guaranteed availability.
22
-
23
- ## Use locally
24
-
25
- For SDK development, run `npm ci` and `npm test` from this repository. The test builds, packs and installs a real tarball in an isolated consumer. `npm pack` also produces an installable local artifact.
26
-
27
- ```js
28
- import { builtins, mapRandomness, replayCoordinator } from '@d20dao/vrf-sdk';
29
- import { coordinatorAbi, epochEntropyAbi } from '@d20dao/vrf-sdk/abi';
30
- const mapping = builtins.d20();
31
- // Use only an independently verified accepted word for real outcomes.
32
- ```
33
-
34
- The root exports ESM and TypeScript declarations; `/epoch` exports epoch helpers. `/abi` exports `coordinatorAbi` and `epochEntropyAbi`, with JSON forms `D20VRFCoordinator.json` and `EpochEntropy.json`. The service implementations have locked empty constructors and explicit initializers. Registry initialization takes `address[4]`; it is not a four-address constructor deployment.
35
-
36
- ## Integrate a consumer
37
-
38
- Solidity imports require compiler 0.8.28 and your compiler's npm resolver:
39
-
40
- - `@d20dao/vrf-sdk/contracts/D20VRFConsumer.sol`
41
- - `@d20dao/vrf-sdk/contracts/interfaces/ID20VRF.sol`
42
- - `@d20dao/vrf-sdk/contracts/libraries/D20VRFRequests.sol`
43
- - `@d20dao/vrf-sdk/contracts/libraries/RandomnessMapping.sol`
44
- - `@d20dao/vrf-sdk/contracts/examples/MiningRandomnessConsumer.sol`
45
-
46
- `examples/DiceConsumer.sol` is one concrete consumer example. It requires exact payment, fixes the player's refund recipient and stores the authenticated raw callback word. Its mapped result is 1 through 20. Mapped callbacks still carry raw bytes32. Keep application actions separate from callbacks; the example does not implement application-payment refunds, claim locking or minting.
47
-
48
- Configure the chain explicitly; there is no implicit Arc network default. Pin the effective coordinator proxy address, initialized configuration and implementation history of both service proxies. Obtain keeper consumer onboarding before live requests. A constructor code-length check, SDK installation or permissionless request acceptance does not guarantee service.
49
-
50
- Timely service requires actual onchain proof acceptance at or before original request time +60 seconds. Callback failure still earns the fee; retryCallback redelivers only the same accepted result. Expired unfulfilled requests refund their fixed recipient or receive refund credit. Application-payment refunds remain separate.
51
-
52
- ## Replay and upgrades
53
-
54
- Use independently trusted successful receipts and state. Decode the registry EpochCommitted packet with decodeEpochEvidencePacket and verify with replayEpochCommitment. Use the original source anchor, exact packet, commit block/time, ordered signers and registry identity. Decode the coordinator FulfillmentEvidence packet with decodeEvidencePacket, then call replayCoordinator with its actual exported input type.
55
-
56
- RequestContext binds both requestBlock and targetBlock. Validate the epoch from the original request block, reconstruct the target from the actual publication block, and compare the event and stored transcript. Proof evidence is 416 bytes; fulfillment calldata is 452 bytes. Neither evidence packet has a version prefix. Choose the decoder from trusted emitter/event context. Decoding and mapping alone are not proof verification; replay does not authenticate RPC or establish receipt inclusion.
57
-
58
- D20VRFCoordinator and EpochEntropy use atomically initialized ERC1967 proxies with owner-authorized UUPS upgrades and two-step ownership transfers. The registry owner can change the committer; the coordinator owner can change fee recipient and keeper share. Upgrade authority can change code and is an explicit trust assumption. Keep requests, balances, credits, epochs and public replay intact across reviewed storage-compatible upgrades.
59
-
60
- For replay, populate configuration.feeRecipient from the initialized initialFeeRecipient, not the current payout address. Use the effective proxy addresses in request and registry context. Operators pin the proxy code, initialized configuration, and BOTH implementation addresses/runtime hashes; the keeper fails closed on an unreviewed implementation change. Existing proof/nonce data must survive the review and restart.
61
-
62
- The keeper share pays the configured registry committer, not an arbitrary proof submitter. Failed transfers become keeper credit. Refund escrow remains protected; callback retries do not pay a second fee share.
63
-
64
- ## Operational and release boundary
65
-
66
- This SDK contains no keeper service, API fetching, proof generation, signer secrets or deployment automation. The canonical keeper has a Docker install wrapper that builds, provisions separately supplied key files and starts from reviewed configuration; inspect its platform-specific guide before use. No deployment or funding is authorized by SDK installation.
67
-
68
- Optional Telegram access is disabled unless a bot token and numeric operator chat are explicitly configured. Only that chat can use read-only /status and /keeper commands. Commands never modify configuration or send transactions; notifications are best-effort observations, not chain evidence. This package neither reads bot credentials nor contacts Telegram.
69
-
70
- Builds use reviewed protocol Git blobs and verify every SHA-256 in PROTOCOL-PROVENANCE.json. BUILD-MANIFEST.json records source, dependency-lock and imported OpenZeppelin hashes. The UUPS build uses OpenZeppelin contracts and contracts-upgradeable 5.6.1. Consumer source is copied exactly; service implementations, operator code, test fixtures and provers are excluded from the tarball.
71
-
72
- Fixture provenance distinguishes explicit CI signatures from actual API3 responses. Fixtures are not included in the package. The browser-target bundle is executed under Node, not an actual browser session; independently trusted chain context is still required for real verification.
73
-
74
- SDK installation provides consumer and verification tooling. Chain availability, provider quotas, upgrade administration and application settlement remain separate concerns. A healthy process alone does not guarantee a particular request's timely fulfillment.
75
-
76
- ## Arc Testnet pilot
77
-
78
- Chain ID: **5042002**. Use the **coordinator proxy** when constructing a consumer.
79
-
80
- | Contract | Role | Arc Testnet address |
81
- | --- | --- | --- |
82
- | D20VRFCoordinator | Consumer entry point / proxy | [`0xd20dA0fDa41f84FCfA3423ae9F96B15910587B4E`](https://testnet.arcscan.app/address/0xd20dA0fDa41f84FCfA3423ae9F96B15910587B4E) |
83
- | EpochEntropy | Epoch registry / proxy | [`0xd20Da04e4D6d97a762A5b56993d723AA7663F204`](https://testnet.arcscan.app/address/0xd20Da04e4D6d97a762A5b56993d723AA7663F204) |
84
- | D20CostClient | Restricted pilot consumer / proxy | [`0xD20Da0Ab4F5c258d579D18dC5a6e652266BB9a20`](https://testnet.arcscan.app/address/0xD20Da0Ab4F5c258d579D18dC5a6e652266BB9a20) |
85
- | D20VRFCoordinator | Implementation | [`0xd20Da05E6bb360edA09a6a360291AB6AD7AA0c58`](https://testnet.arcscan.app/address/0xd20Da05E6bb360edA09a6a360291AB6AD7AA0c58) |
86
- | EpochEntropy | Implementation | [`0xd20Da0028F2B65d8c8C8512C7029EE02F94E8BF2`](https://testnet.arcscan.app/address/0xd20Da0028F2B65d8c8C8512C7029EE02F94E8BF2) |
87
- | D20CostClient | Implementation | [`0xd20dA0Ec8d33fB04184CbC13942657bDC1f5Bbc0`](https://testnet.arcscan.app/address/0xd20dA0Ec8d33fB04184CbC13942657bDC1f5Bbc0) |
88
-
89
- Addresses are copied from the deployment manifest, including the coordinator upgrade at block 62310349. Explorer links identify addresses; they do not assert explorer source-code verification. Implementation addresses can change through owner-authorized upgrades. The pilot consumer is test tooling, not a shared application entry point.
90
-
91
- A restricted pilot is deployed on chain 5042002. Obtain current proxy addresses and independently checked code hashes from the [keeper deployment manifest](https://github.com/d20dao/keeper/blob/main/deployments/arc-testnet.json). Consumer allowlisting is required. The manifest includes the activated refund-notification implementation. The [small-sample measurements](https://github.com/d20dao/keeper/blob/main/docs/benchmarks/arc-testnet-pilot-2026-09-15.json) cover proof acceptance, same-result callback repair and expired-request refunds; they are not an SLA.
92
-
93
- ## Optional refund notification
94
-
95
- A coordinator with refund-hook support calls `onRefund(requestId)` on the original consumer after the fee is paid to its fixed refund address or recorded as backed credit. Extend `D20VRFConsumer` and override `_onRefund(uint256 requestId)` to update application state; the base authenticates the coordinator. The callback only carries the request ID and does not imply that the consumer itself received money. Application assets and fees remain the application's responsibility.
96
-
97
- The first attempt forwards 100,000 gas. A reverting or gas-exhausting hook cannot undo the fee settlement. After failure, `retryRefundCallback(requestId, gasLimit)` retries the notification without another payment; successful delivery is recorded by `refundCallbackDelivered(requestId)`. Refund/retry needs sufficient outer gas. Never request new randomness from within either callback; use a separate application transaction.
98
-
1
+ # d20dao VRF SDK
2
+
3
+ Public replay, mapping, epoch evidence and Solidity consumer helpers for a general randomness service. Package: `@d20dao/vrf-sdk` `0.1.2`.
4
+
5
+ ## Getting started
6
+
7
+ ```sh
8
+ npm install @d20dao/vrf-sdk
9
+ ```
10
+
11
+ Use Node 22.13 or newer and Solidity 0.8.28. Configure the coordinator proxy from the [current deployment manifest](https://github.com/d20dao/keeper/blob/main/deployments/arc-testnet.json), then follow the consumer example below. Arc Testnet is chain 5042002; any consumer contract can request randomness with the current exact fee, without allowlisting. Read `requestFee()` at runtime and keep application payments separate.
12
+
13
+ For agent-assisted integration, give your agent the installed `AGENTS.md` and `PROTOCOL-PROVENANCE.json`, plus the [integration skills](https://github.com/d20dao/skills). Website guides include Getting started, Copy prompt, `/llms.txt`, `/llms-full.txt` and `/agents.md`.
14
+
15
+ ## Current request flow
16
+
17
+ Epochs last 200 blocks. The keeper selects one of four fixed recipes using the canonical block hash at epoch start minus one and prepares its first validated API3 snapshot locally. Idle preparation publishes no transaction. An unused local snapshot can be retained for 50 epochs (10,000 blocks), subject to live-demand and unresolved-transaction protection.
18
+
19
+ After activation, a consumer escrows the exact request fee even when the epoch packet is not published. The request fixes its original block, epoch, client seed, mapping, recipient and 60-second deadline. The keeper publishes the saved packet only for live paid demand. The randomness target becomes `max(requestBlock, committedBlock + 1)`, so its hash is unknown at publication. Before publication the request has no usable target or VRF seed. Multiple requests share the packet, and timely requests can settle across epoch boundaries without changing their epoch.
20
+
21
+ The four ordered recipe slots are Hyperliquid BTC volume, ANU quantum data, TickerLayer BTCUSD lastTrade and TickerLayer ETHUSD lastTrade. Both TickerLayer slots use the same provider signer and crypto asset class. `EpochSigners` is a readonly four-address tuple. The full exact signed data is limited to 128 bytes and emitted publicly; do not crop or replace it. A signature establishes provider-wrapper provenance, not unbiased upstream data or guaranteed availability.
22
+
23
+ ## Use locally
24
+
25
+ For SDK development, run `npm ci` and `npm test` from this repository. The test builds, packs and installs a real tarball in an isolated consumer. `npm pack` also produces an installable local artifact.
26
+
27
+ ```js
28
+ import { builtins, mapRandomness, replayCoordinator } from '@d20dao/vrf-sdk';
29
+ import { coordinatorAbi, epochEntropyAbi } from '@d20dao/vrf-sdk/abi';
30
+ const mapping = builtins.d20();
31
+ // Use only an independently verified accepted word for real outcomes.
32
+ ```
33
+
34
+ The root exports ESM and TypeScript declarations; `/epoch` exports epoch helpers. `/abi` exports `coordinatorAbi` and `epochEntropyAbi`, with JSON forms `D20VRFCoordinator.json` and `EpochEntropy.json`. The service implementations have locked empty constructors and explicit initializers. Registry initialization takes `address[4]`; it is not a four-address constructor deployment.
35
+
36
+ ## Integrate a consumer
37
+
38
+ Solidity imports require compiler 0.8.28 and your compiler's npm resolver:
39
+
40
+ - `@d20dao/vrf-sdk/contracts/D20VRFConsumer.sol`
41
+ - `@d20dao/vrf-sdk/contracts/interfaces/ID20VRF.sol`
42
+ - `@d20dao/vrf-sdk/contracts/libraries/D20VRFRequests.sol`
43
+ - `@d20dao/vrf-sdk/contracts/libraries/RandomnessMapping.sol`
44
+ - `@d20dao/vrf-sdk/contracts/examples/MiningRandomnessConsumer.sol`
45
+
46
+ `examples/DiceConsumer.sol` is one concrete consumer example. It requires exact payment, fixes the player's refund recipient and stores the authenticated raw callback word. Its mapped result is 1 through 20. Mapped callbacks still carry raw bytes32. Keep application actions separate from callbacks; the example does not implement application-payment refunds, claim locking or minting.
47
+
48
+ Configure the chain explicitly; there is no implicit Arc network default. Pin the effective coordinator proxy address, initialized configuration and implementation history of both service proxies. Any consumer contract may request by paying the current exact fee. A constructor code-length check, SDK installation or permissionless request acceptance does not guarantee service.
49
+
50
+ Timely service requires actual onchain proof acceptance at or before original request time +60 seconds. Callback failure still earns the fee; retryCallback redelivers only the same accepted result. Expired unfulfilled requests refund their fixed recipient or receive refund credit. Application-payment refunds remain separate.
51
+
52
+ ## Replay and upgrades
53
+
54
+ Use independently trusted successful receipts and state. Decode the registry EpochCommitted packet with decodeEpochEvidencePacket and verify with replayEpochCommitment. Use the original source anchor, exact packet, commit block/time, ordered signers and registry identity. Decode the coordinator FulfillmentEvidence packet with decodeEvidencePacket, then call replayCoordinator with its actual exported input type.
55
+
56
+ RequestContext binds both requestBlock and targetBlock. Validate the epoch from the original request block, reconstruct the target from the actual publication block, and compare the event and stored transcript. Proof evidence is 416 bytes; fulfillment calldata is 452 bytes. Neither evidence packet has a version prefix. Choose the decoder from trusted emitter/event context. Decoding and mapping alone are not proof verification; replay does not authenticate RPC or establish receipt inclusion.
57
+
58
+ D20VRFCoordinator and EpochEntropy use atomically initialized ERC1967 proxies with owner-authorized UUPS upgrades and two-step ownership transfers. The registry owner can change the committer; the coordinator owner can change fee recipient and keeper share. Upgrade authority can change code and is an explicit trust assumption. Keep requests, balances, credits, epochs and public replay intact across reviewed storage-compatible upgrades.
59
+
60
+ For replay, populate configuration.feeRecipient from the initialized initialFeeRecipient, not the current payout address. Use the effective proxy addresses in request and registry context. Operators pin the proxy code, initialized configuration, and BOTH implementation addresses/runtime hashes; the keeper fails closed on an unreviewed implementation change. Existing proof/nonce data must survive the review and restart.
61
+
62
+ The keeper share pays the configured registry committer, not an arbitrary proof submitter. Failed transfers become keeper credit. Refund escrow remains protected; callback retries do not pay a second fee share.
63
+
64
+ ## Operational and release boundary
65
+
66
+ This SDK contains no keeper service, API fetching, proof generation, signer secrets or deployment automation. The canonical keeper has a Docker install wrapper that builds, provisions separately supplied key files and starts from reviewed configuration; inspect its platform-specific guide before use. No deployment or funding is authorized by SDK installation.
67
+
68
+ Optional Telegram access is disabled unless a bot token and numeric operator chat are explicitly configured. Only that chat can use read-only /status and /keeper commands. Commands never modify configuration or send transactions; notifications are best-effort observations, not chain evidence. This package neither reads bot credentials nor contacts Telegram.
69
+
70
+ Builds use reviewed protocol Git blobs and verify every SHA-256 in PROTOCOL-PROVENANCE.json. BUILD-MANIFEST.json records source, dependency-lock and imported OpenZeppelin hashes. The UUPS build uses OpenZeppelin contracts and contracts-upgradeable 5.6.1. Consumer source is copied exactly; service implementations, operator code, test fixtures and provers are excluded from the tarball.
71
+
72
+ Fixture provenance distinguishes explicit CI signatures from actual API3 responses. Fixtures are not included in the package. The browser-target bundle is executed under Node, not an actual browser session; independently trusted chain context is still required for real verification.
73
+
74
+ SDK installation provides consumer and verification tooling. Chain availability, provider quotas, upgrade administration and application settlement remain separate concerns. A healthy process alone does not guarantee a particular request's timely fulfillment.
75
+
76
+ ## Arc Testnet pilot
77
+
78
+ Chain ID: **5042002**. Use the **coordinator proxy** when constructing a consumer.
79
+
80
+ | Contract | Role | Arc Testnet address |
81
+ | --- | --- | --- |
82
+ | D20VRFCoordinator | Consumer entry point / proxy | [`0xd20dA0fDa41f84FCfA3423ae9F96B15910587B4E`](https://testnet.arcscan.app/address/0xd20dA0fDa41f84FCfA3423ae9F96B15910587B4E) |
83
+ | EpochEntropy | Epoch registry / proxy | [`0xd20Da04e4D6d97a762A5b56993d723AA7663F204`](https://testnet.arcscan.app/address/0xd20Da04e4D6d97a762A5b56993d723AA7663F204) |
84
+ | D20CostClient | Restricted pilot consumer / proxy | [`0xD20Da0Ab4F5c258d579D18dC5a6e652266BB9a20`](https://testnet.arcscan.app/address/0xD20Da0Ab4F5c258d579D18dC5a6e652266BB9a20) |
85
+ | D20VRFCoordinator | Implementation | [`0xd20Da05E6bb360edA09a6a360291AB6AD7AA0c58`](https://testnet.arcscan.app/address/0xd20Da05E6bb360edA09a6a360291AB6AD7AA0c58) |
86
+ | EpochEntropy | Implementation | [`0xd20Da0028F2B65d8c8C8512C7029EE02F94E8BF2`](https://testnet.arcscan.app/address/0xd20Da0028F2B65d8c8C8512C7029EE02F94E8BF2) |
87
+ | D20CostClient | Implementation | [`0xd20dA0Ec8d33fB04184CbC13942657bDC1f5Bbc0`](https://testnet.arcscan.app/address/0xd20dA0Ec8d33fB04184CbC13942657bDC1f5Bbc0) |
88
+
89
+ Addresses are copied from the deployment manifest, including the coordinator upgrade at block 62310349. Explorer links identify addresses; they do not assert explorer source-code verification. Implementation addresses can change through owner-authorized upgrades. The pilot consumer is test tooling, not a shared application entry point.
90
+
91
+ A public testnet service is deployed on chain 5042002. Obtain current proxy addresses and independently checked code hashes from the [keeper deployment manifest](https://github.com/d20dao/keeper/blob/main/deployments/arc-testnet.json). Any consumer contract can request service by paying the current exact fee; no allowlist is required. The manifest includes the activated refund-notification implementation. The [small-sample measurements](https://github.com/d20dao/keeper/blob/main/docs/benchmarks/arc-testnet-pilot-2026-09-15.json) cover proof acceptance, same-result callback repair and expired-request refunds; they are not an SLA.
92
+
93
+ ## Optional refund notification
94
+
95
+ A coordinator with refund-hook support calls `onRefund(requestId)` on the original consumer after the fee is paid to its fixed refund address or recorded as backed credit. Extend `D20VRFConsumer` and override `_onRefund(uint256 requestId)` to update application state; the base authenticates the coordinator. The callback only carries the request ID and does not imply that the consumer itself received money. Application assets and fees remain the application's responsibility.
96
+
97
+ The first attempt forwards 100,000 gas. A reverting or gas-exhausting hook cannot undo the fee settlement. After failure, `retryRefundCallback(requestId, gasLimit)` retries the notification without another payment; successful delivery is recorded by `refundCallbackDelivered(requestId)`. Refund/retry needs sufficient outer gas. Never request new randomness from within either callback; use a separate application transaction.
98
+
99
99
  This SDK includes the new source interface. Installing it does not upgrade a deployed coordinator: verify the implementation and its refund-hook capability before relying on notification delivery.
package/package.json CHANGED
@@ -1,73 +1,76 @@
1
- {
2
- "name": "@d20dao/vrf-sdk",
3
- "version": "0.1.1",
4
- "description": "D20DAO verifiable randomness: Solidity consumer helpers, contract ABIs and public proof replay",
5
- "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" },
6
- "type": "module",
7
- "license": "MIT",
8
- "engines": {
9
- "node": ">=22.13.0"
10
- },
11
- "main": "./dist/index.js",
12
- "types": "./dist/index.d.ts",
13
- "exports": {
14
- ".": {
15
- "types": "./dist/index.d.ts",
16
- "import": "./dist/index.js"
17
- },
18
- "./abi": {
19
- "types": "./dist/abi.d.ts",
20
- "import": "./dist/abi.js"
21
- },
22
- "./epoch": {
23
- "types": "./dist/epoch.d.ts",
24
- "import": "./dist/epoch.js"
25
- },
26
- "./abi/D20VRFCoordinator.json": "./abi/D20VRFCoordinator.json",
27
- "./abi/EpochEntropy.json": "./abi/EpochEntropy.json",
28
- "./contracts/*": "./contracts/*",
29
- "./examples/*": "./examples/*",
30
- "./AGENTS.md": "./AGENTS.md"
31
- },
32
- "files": [
33
- "dist/*.js",
34
- "dist/*.d.ts",
35
- "contracts/**/*.sol",
36
- "examples/*.sol",
37
- "AGENTS.md",
38
- "LICENSE",
39
- "THIRD_PARTY_NOTICES.md",
40
- "notices/*",
41
- "BUILD-MANIFEST.json",
42
- "PROTOCOL-PROVENANCE.json",
43
- "abi/D20VRFCoordinator.json",
44
- "abi/EpochEntropy.json"
45
- ],
46
- "scripts": {
47
- "build": "node scripts/build.mjs",
48
- "prepack": "npm run build",
49
- "prepublishOnly": "npm test",
50
- "test": "node scripts/smoke.mjs"
51
- },
52
- "dependencies": {
53
- "@noble/curves": "1.9.7",
54
- "ethers": "6.17.0"
55
- },
56
- "devDependencies": {
57
- "@openzeppelin/contracts": "5.6.1",
58
- "@types/node": "24.10.0",
59
- "esbuild": "0.28.2",
60
- "solc": "0.8.28",
61
- "typescript": "5.9.3",
62
- "@openzeppelin/contracts-upgradeable": "5.6.1"
63
- },
64
- "overrides": {
65
- "solc": {
66
- "tmp": "0.2.7"
67
- }
68
- },
69
- "repository": {
70
- "type": "git",
71
- "url": "https://github.com/d20dao/d20-sdk.git"
72
- }
73
- }
1
+ {
2
+ "name": "@d20dao/vrf-sdk",
3
+ "version": "0.1.2",
4
+ "description": "D20DAO verifiable randomness: Solidity consumer helpers, contract ABIs and public proof replay",
5
+ "publishConfig": {
6
+ "access": "public",
7
+ "registry": "https://registry.npmjs.org/"
8
+ },
9
+ "type": "module",
10
+ "license": "MIT",
11
+ "engines": {
12
+ "node": ">=22.13.0"
13
+ },
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ },
21
+ "./abi": {
22
+ "types": "./dist/abi.d.ts",
23
+ "import": "./dist/abi.js"
24
+ },
25
+ "./epoch": {
26
+ "types": "./dist/epoch.d.ts",
27
+ "import": "./dist/epoch.js"
28
+ },
29
+ "./abi/D20VRFCoordinator.json": "./abi/D20VRFCoordinator.json",
30
+ "./abi/EpochEntropy.json": "./abi/EpochEntropy.json",
31
+ "./contracts/*": "./contracts/*",
32
+ "./examples/*": "./examples/*",
33
+ "./AGENTS.md": "./AGENTS.md"
34
+ },
35
+ "files": [
36
+ "dist/*.js",
37
+ "dist/*.d.ts",
38
+ "contracts/**/*.sol",
39
+ "examples/*.sol",
40
+ "AGENTS.md",
41
+ "LICENSE",
42
+ "THIRD_PARTY_NOTICES.md",
43
+ "notices/*",
44
+ "BUILD-MANIFEST.json",
45
+ "PROTOCOL-PROVENANCE.json",
46
+ "abi/D20VRFCoordinator.json",
47
+ "abi/EpochEntropy.json"
48
+ ],
49
+ "scripts": {
50
+ "build": "node scripts/build.mjs",
51
+ "prepack": "npm run build",
52
+ "prepublishOnly": "npm test",
53
+ "test": "node scripts/smoke.mjs"
54
+ },
55
+ "dependencies": {
56
+ "@noble/curves": "1.9.7",
57
+ "ethers": "6.17.0"
58
+ },
59
+ "devDependencies": {
60
+ "@openzeppelin/contracts": "5.6.1",
61
+ "@types/node": "24.10.0",
62
+ "esbuild": "0.28.2",
63
+ "solc": "0.8.28",
64
+ "typescript": "5.9.3",
65
+ "@openzeppelin/contracts-upgradeable": "5.6.1"
66
+ },
67
+ "overrides": {
68
+ "solc": {
69
+ "tmp": "0.2.7"
70
+ }
71
+ },
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "https://github.com/d20dao/d20-sdk.git"
75
+ }
76
+ }