@elisym/merchant-node 0.2.0 → 0.3.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 +59 -33
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @elisym/merchant-node
|
|
2
2
|
|
|
3
3
|
The self-hosted store behind the elisym checkout. It publishes your product to Nostr, takes
|
|
4
|
-
orders sent by the checkout widget, checks each
|
|
5
|
-
buyer what they bought.
|
|
4
|
+
orders sent by the checkout widget, checks each payment on chain (USDC on Solana, or a
|
|
5
|
+
stablecoin on Tempo), and sends the buyer what they bought.
|
|
6
6
|
|
|
7
7
|
You do not need an account or a server of ours. The node holds your store's keys and a small
|
|
8
8
|
ledger on your own disk.
|
|
@@ -10,9 +10,10 @@ ledger on your own disk.
|
|
|
10
10
|
## What you need
|
|
11
11
|
|
|
12
12
|
- Node.js 22.4 or newer, or Docker.
|
|
13
|
-
- A Solana wallet address to be paid to (USDC).
|
|
14
|
-
-
|
|
15
|
-
(Helius, Triton, ...). A key restricted to a browser origin does not work from a
|
|
13
|
+
- A Solana wallet address to be paid to (USDC), a Tempo address, or both.
|
|
14
|
+
- For Solana payouts, a Solana RPC endpoint for the node itself. On mainnet, use your own
|
|
15
|
+
provider key (Helius, Triton, ...). A key restricted to a browser origin does not work from a
|
|
16
|
+
server. Tempo is read through its public endpoint unless you set your own.
|
|
16
17
|
- What the buyer gets once paid: a link (a Blossom URL, a course page, a download) or text
|
|
17
18
|
(a license key).
|
|
18
19
|
|
|
@@ -53,13 +54,15 @@ Gift wraps stay on the relays for two days, and payments are read back from the
|
|
|
53
54
|
|
|
54
55
|
## Commands
|
|
55
56
|
|
|
56
|
-
| Command
|
|
57
|
-
|
|
|
58
|
-
| `init`
|
|
59
|
-
| `setup`
|
|
60
|
-
| `run`
|
|
61
|
-
| `orders`
|
|
62
|
-
| `check`
|
|
57
|
+
| Command | What it does |
|
|
58
|
+
| --------- | ----------------------------------------------------------------------------------- |
|
|
59
|
+
| `init` | Creates the home: a `config.json` template (never overwritten) and the store's keys |
|
|
60
|
+
| `setup` | Checks the inbox relays, publishes the store, and records the terms it offers |
|
|
61
|
+
| `run` | Takes orders, verifies payments and delivers |
|
|
62
|
+
| `orders` | Lists the orders: open, paid, delivered, and the buyer's email |
|
|
63
|
+
| `check` | Checks the inbox relays, the owner's payout list and the domain |
|
|
64
|
+
| `deliver` | Answers an unpaid order by hand with the configured delivery (node stopped) |
|
|
65
|
+
| `refund` | Answers an unpaid order by hand with a refund you already sent (node stopped) |
|
|
63
66
|
|
|
64
67
|
Every command takes `--home <dir>`. Without it, the home is `$ELISYM_MERCHANT_HOME`, else
|
|
65
68
|
`~/.elisym-merchant`.
|
|
@@ -83,21 +86,22 @@ it starts.
|
|
|
83
86
|
|
|
84
87
|
## The config
|
|
85
88
|
|
|
86
|
-
| Field | Meaning
|
|
87
|
-
| ------------------------- |
|
|
88
|
-
| `name` | The store's name, shown in the checkout
|
|
89
|
-
| `nip05` | Optional. `_@your-domain.com` for level A (see below)
|
|
90
|
-
| `network` | `devnet` or `mainnet`
|
|
91
|
-
| `rpcUrl` | The node's Solana RPC (`https:`)
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `product.
|
|
95
|
-
| `product.
|
|
96
|
-
| `product.
|
|
97
|
-
| `product.
|
|
98
|
-
| `product.
|
|
99
|
-
| `product.delivery.
|
|
100
|
-
| `
|
|
89
|
+
| Field | Meaning |
|
|
90
|
+
| ------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
91
|
+
| `name` | The store's name, shown in the checkout |
|
|
92
|
+
| `nip05` | Optional. `_@your-domain.com` for level A (see below) |
|
|
93
|
+
| `network` | `devnet` or `mainnet` |
|
|
94
|
+
| `rpcUrl` | The node's Solana RPC (`https:`). Needed with a Solana payout |
|
|
95
|
+
| `tempo` | Optional. `{ "network": ... }` matching `network` (`moderato` on devnet), plus an optional `rpcUrl` |
|
|
96
|
+
| `inboxRelays` | 1 to 5 relays (`wss:`) where the store reads orders and replies |
|
|
97
|
+
| `product.d` | The product's id in the store (letters, digits, `.`, `-`, `_`) |
|
|
98
|
+
| `product.title` | Title |
|
|
99
|
+
| `product.description` | Description |
|
|
100
|
+
| `product.summary` | Optional short line |
|
|
101
|
+
| `product.priceUsd` | Price in USD, such as `"49"` or `"0.50"` |
|
|
102
|
+
| `product.delivery.method` | `access`, `download`, `license`, `api` or `webhook`: how the checkout labels it |
|
|
103
|
+
| `product.delivery.value` | The link or text the buyer gets (up to 1024 characters) |
|
|
104
|
+
| `payouts` | One `{ "caip19": ..., "address": ... }` per coin, see [Tempo payouts](#tempo-payouts) |
|
|
101
105
|
|
|
102
106
|
The node refuses to start with a config it cannot use, and names every problem.
|
|
103
107
|
|
|
@@ -117,6 +121,26 @@ after the payment, one relay is enough. If a relay later drops a delivery, the n
|
|
|
117
121
|
status again when it reads that order or a receipt for it again: at most every ten minutes per
|
|
118
122
|
order, and a few at a time (the rest wait until the order is read again).
|
|
119
123
|
|
|
124
|
+
### Tempo payouts
|
|
125
|
+
|
|
126
|
+
A store can also take a Tempo stablecoin, paid with an EIP-6963 wallet such as MetaMask. Add a
|
|
127
|
+
`tempo` block naming the Tempo network that matches the node's `network` (`mainnet` on mainnet,
|
|
128
|
+
`moderato` on devnet), and one payout per coin, with your Tempo address in
|
|
129
|
+
lowercase:
|
|
130
|
+
|
|
131
|
+
| Network | `tempo.network` | Coin | `caip19` |
|
|
132
|
+
| ------------------ | --------------- | ------- | --------------------------------------------------------------- |
|
|
133
|
+
| Tempo mainnet | `mainnet` | USDC.e | `eip155:4217/erc20:0x20c000000000000000000000b9537d11c60e8b50` |
|
|
134
|
+
| Tempo mainnet | `mainnet` | pathUSD | `eip155:4217/erc20:0x20c0000000000000000000000000000000000000` |
|
|
135
|
+
| Moderato (testnet) | `moderato` | pathUSD | `eip155:42431/erc20:0x20c0000000000000000000000000000000000000` |
|
|
136
|
+
|
|
137
|
+
A Tempo payout is refused without the `tempo` block, and a store with only Tempo payouts needs
|
|
138
|
+
no Solana `rpcUrl`, but it still names its network: `"network": "mainnet"` for Tempo mainnet
|
|
139
|
+
(`init` writes `devnet` unless told `--network mainnet`). A page shows the store's payouts on its own network, and the buyer picks
|
|
140
|
+
one. Upgrade
|
|
141
|
+
the node before the payout list names a Tempo address, and do not downgrade it afterwards: once
|
|
142
|
+
the node has seen a Tempo order, an older node refuses its ledger.
|
|
143
|
+
|
|
120
144
|
## Level A: your domain vouches for the store
|
|
121
145
|
|
|
122
146
|
Without `nip05`, the store is level C. The checkout then shows the buyer that no domain vouches
|
|
@@ -157,10 +181,10 @@ To edit the config in the volume, mount a host directory instead, for example
|
|
|
157
181
|
- `keys.json` holds the store key and the owner key. Whoever has them can publish a different
|
|
158
182
|
payout address in your store's name. Keep the home private (the node creates it as `0700`)
|
|
159
183
|
and back it up. A lost key means a new store.
|
|
160
|
-
- The owner's payout list must name only payouts this node checks:
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
record. A buyer could pay that address and never get a delivery. It refuses the same way
|
|
184
|
+
- The owner's payout list must name only payouts this node checks: on its networks, at the
|
|
185
|
+
addresses its ledger records. `run` refuses to start when the published list names another
|
|
186
|
+
one, for example a Tempo address added from elsewhere without a `tempo` block, or an address
|
|
187
|
+
`setup` did not record. A buyer could pay that address and never get a delivery. It refuses the same way
|
|
164
188
|
when the published listing asks a price the ledger does not record (a `setup` killed
|
|
165
189
|
between publishing and recording, for example by `docker stop`), and when the published
|
|
166
190
|
inbox list names a relay the node does not read (the config changed without `setup`). Run
|
|
@@ -172,7 +196,9 @@ To edit the config in the volume, mount a host directory instead, for example
|
|
|
172
196
|
|
|
173
197
|
## Limits
|
|
174
198
|
|
|
175
|
-
- One product per node,
|
|
199
|
+
- One product per node, on one network: USDC on Solana and stablecoins on Tempo (Moderato on
|
|
200
|
+
devnet).
|
|
176
201
|
- Delivery is the configured link or text. Uploading a file to Blossom is up to you; the link
|
|
177
202
|
goes in `product.delivery.value`.
|
|
178
|
-
- Refunds are made by hand from your wallet.
|
|
203
|
+
- Refunds are made by hand from your wallet. `refund` reports one to the buyer of an order the
|
|
204
|
+
node did not credit; a refund of a delivered order is between you and the buyer.
|
package/dist/cli.js
CHANGED
|
@@ -406,6 +406,13 @@ var configSchema = z.object({
|
|
|
406
406
|
}
|
|
407
407
|
seen.add(caip19.id);
|
|
408
408
|
});
|
|
409
|
+
if (config.tempo !== void 0 && tempoRegistryNetwork(config.tempo.network) !== config.network) {
|
|
410
|
+
context.addIssue({
|
|
411
|
+
code: "custom",
|
|
412
|
+
path: ["tempo", "network"],
|
|
413
|
+
message: `is ${config.tempo.network}, the node runs on ${config.network}: use network "mainnet" with Tempo "mainnet", or network "devnet" with Tempo "moderato"`
|
|
414
|
+
});
|
|
415
|
+
}
|
|
409
416
|
if (solanaPayouts > 0 && config.rpcUrl === void 0) {
|
|
410
417
|
context.addIssue({
|
|
411
418
|
code: "custom",
|