Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ With a pre-built metadata URI:
rare mint --contract <address> --token-uri <ipfs://...> [--to <address>] [--royalty-receiver <address>] [--chain <chain>]
```

### Backup

Resolve an existing token, quote its billable bytes, and optionally preserve it through a hosted x402-backed service:

```bash
rare backup token --contract <addr> --token-id <id> [--chain <chain>] --quote-only
rare backup token --contract <addr> --token-id <id> [--chain <chain>] --payment-chain <chain>
rare backup token --contract <addr> --token-id <id> [--chain-id <id>] [--payment-chain-id <id>]
```

Backup requests default to `https://api.superrare.com`, and IPFS fetches/receipt links default to `https://superrare.myfilebase.com`.

### Auction Lifecycle

```bash
Expand Down
52 changes: 51 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,42 @@ rare mint \
--royalty-receiver 0x...
```

### Back Up an Existing NFT

Resolve an existing token's `tokenURI`, fetch its metadata and directly referenced media locally, request a hosted preservation quote, and optionally pay/pin via x402 using `RARE`.

```bash
# Quote only
rare backup token \
--contract 0x... \
--token-id 1 \
--chain sepolia \
--quote-only

# Full preserve flow
rare backup token \
--contract 0x... \
--token-id 1 \
--chain-id 1 \
--payment-chain base
```

Useful options:

```bash
rare backup token \
--contract 0x... \
--token-id 1 \
--service-url https://your-preservation-service.com \
--max-bytes 1073741824
```

The CLI defaults to `https://api.superrare.com` for preservation requests and uses `https://superrare.myfilebase.com` as its IPFS gateway. Use `--service-url` only when you need to point the backup flow at a different API host.

For paid preserves, the selected `--payment-chain` or `--payment-chain-id` must have both a private key and RPC URL configured. The backup flow does not auto-generate wallets. Before any payment-capable request, the CLI now prints the quote and asks for confirmation. Use `--yes` to skip the prompt in automation.

Preservation currently only supports CID-backed IPFS metadata and media references. Use `ipfs://...` URIs or IPFS gateway URLs like `https://ipfs.io/ipfs/<cid>...`.

### Auctions

```bash
Expand Down Expand Up @@ -317,6 +353,21 @@ await rare.import.erc721({
});
```

### Quote or preserve an existing NFT

`backup.quoteTokenPreservation` resolves metadata/media locally, computes exact byte counts and hashes, then requests a hosted quote. `backup.preserveToken` continues through upload session creation, uploads the staged bytes, and finalizes the receipt.

```ts
const quote = await rare.backup.quoteTokenPreservation({
serviceUrl: 'https://your-preservation-service.com',
contract: '0xYourContractAddress',
tokenId: '1',
sourceChain: 'sepolia',
});

console.log(quote.billableBytes, quote.tokenAmount);
```

## Configuration

Config is stored at `~/.rare/config.json`. Each chain has its own private key and RPC URL.
Expand All @@ -334,7 +385,6 @@ rare configure --default-chain mainnet

# View current config
rare configure --show
```

## Best Practices

Expand Down
112 changes: 112 additions & 0 deletions docs/preservation-seller.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Preservation Seller Service

This CLI now expects a separate hosted preservation service for paid IPFS backup flows. The service is not part of `rare-cli`; this document captures the buyer-facing contract and the intended x402 seller responsibilities.

## Responsibilities

- Accept unpaid preservation quote requests.
- Challenge paid upload-session requests with `402 Payment Required`.
- Verify `x402` payments in `RARE` on one of:
- `mainnet`
- `sepolia`
- `base`
- `base-sepolia`
- Return upload targets after payment succeeds.
- Verify uploaded byte counts and SHA-256 hashes against the quoted asset descriptors.
- Pin verified bytes to IPFS.
- Assemble and pin a preservation manifest.
- Return a private receipt to the payer.

## Expected Routes

- `POST /v1/preservations/quotes`
- `POST /v1/preservations/quotes/:quoteId/upload-session`
- `POST /v1/preservations/quotes/:quoteId/finalize`
- `GET /v1/preservations/receipts/:receiptId`

## Quote Request Shape

```json
{
"source": {
"chain": "sepolia",
"chainId": 11155111,
"contractAddress": "0x...",
"tokenId": "1",
"universalTokenId": "11155111-0x...-1",
"tokenUri": "ipfs://..."
},
"assets": [
{
"assetId": "asset_0000",
"role": "metadata",
"originalUri": "ipfs://...",
"filename": "metadata.json",
"mimeType": "application/json",
"size": 1234,
"sha256": "..."
}
],
"preferredPaymentChain": "base"
}
```

## Quote Response Shape

```json
{
"quoteId": "quote_123",
"expiresAt": "2026-01-01T00:00:00.000Z",
"billableBytes": 1234,
"tokenAmount": "86000460000000",
"ratePerByteAtomic": "69690000000",
"source": {},
"assets": [],
"acceptedPayments": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x691077c8e8de54ea84efd454630439f99bd8c92f",
"payTo": "0xReceivingWallet",
"amount": "86000460000000",
"maxTimeoutSeconds": 300,
"extra": null
}
]
}
```

## Finalize Response Shape

`POST /v1/preservations/quotes/:quoteId/finalize` should return a receipt payload. The CLI can derive fallback values for the manifest gateway link and quote expiration, but sellers should prefer returning them explicitly:

```json
{
"receiptId": "receipt_123",
"quoteId": "quote_123",
"expiresAt": "2026-01-01T00:05:00.000Z",
"manifestCid": "bafy...",
"manifestIpfsUrl": "ipfs://bafy...",
"manifestGatewayUrl": "https://your.gateway/ipfs/bafy...",
"billableBytes": 1234,
"payment": {},
"assets": [],
"source": {},
"createdAt": "2026-01-01T00:01:00.000Z"
}
```

## Pricing

- Rate: `0.00006969 RARE / kb`
- `kb` is `1000` bytes
- Billing is exact-bytes, not rounded buckets
- Atomic rate: `69_690_000_000`
- Formula: `totalChargeAtomic = totalBillableBytes * 69_690_000_000`

## x402 Notes

- The CLI buyer uses the official `@x402/fetch` and `@x402/evm` packages.
- The hosted seller should use the official `x402` seller middleware/helpers.
- The service should advertise the `payment-identifier` extension so retries can be de-duplicated safely.
- The monetized boundary is the hosted service. The CLI is open source and can be forked; payment enforcement only applies to the hosted seller.
63 changes: 61 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,15 @@
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"generate:types": "openapi-typescript https://rare-api-8426-784573620320.us-east1.run.app/doc -o src/data-access/schema.d.ts",
"generate:types": "openapi-typescript https://api.superrare.com/doc -o src/data-access/schema.d.ts",
"test": "npm run build && node --test test/**/*.test.mjs",
"prepare": "npm run build",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@rareprotocol/rare-cli": "^0.4.1",
"@x402/evm": "^2.10.0",
"@x402/fetch": "^2.10.0",
"commander": "^12.0.0",
"openapi-fetch": "^0.17.0",
"viem": "^2.0.0"
Expand Down
Loading