@v3finance/core-sdk 0.2.1 → 0.2.3

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +2 -1
  3. package/dist/cjs/generated/operations.js +1 -1
  4. package/dist/cjs/generated/types.d.ts +13 -7
  5. package/dist/cjs/generated/types.d.ts.map +1 -1
  6. package/dist/cjs/resources/approvals.d.ts +22 -0
  7. package/dist/cjs/resources/approvals.d.ts.map +1 -1
  8. package/dist/cjs/resources/approvals.js +22 -0
  9. package/dist/cjs/resources/approvals.js.map +1 -1
  10. package/dist/cjs/resources/transfers.d.ts +64 -16
  11. package/dist/cjs/resources/transfers.d.ts.map +1 -1
  12. package/dist/cjs/resources/transfers.js +64 -16
  13. package/dist/cjs/resources/transfers.js.map +1 -1
  14. package/dist/cjs/version.d.ts +1 -1
  15. package/dist/cjs/version.js +1 -1
  16. package/dist/esm/generated/operations.js +1 -1
  17. package/dist/esm/generated/types.d.ts +13 -7
  18. package/dist/esm/generated/types.d.ts.map +1 -1
  19. package/dist/esm/resources/approvals.d.ts +22 -0
  20. package/dist/esm/resources/approvals.d.ts.map +1 -1
  21. package/dist/esm/resources/approvals.js +22 -0
  22. package/dist/esm/resources/approvals.js.map +1 -1
  23. package/dist/esm/resources/transfers.d.ts +64 -16
  24. package/dist/esm/resources/transfers.d.ts.map +1 -1
  25. package/dist/esm/resources/transfers.js +64 -16
  26. package/dist/esm/resources/transfers.js.map +1 -1
  27. package/dist/esm/version.d.ts +1 -1
  28. package/dist/esm/version.js +1 -1
  29. package/docs/concepts.md +2 -1
  30. package/docs/errors.md +36 -16
  31. package/package.json +1 -1
  32. package/src/generated/operations.ts +1 -1
  33. package/src/generated/types.ts +13 -7
  34. package/src/resources/approvals.ts +22 -0
  35. package/src/resources/transfers.ts +64 -16
  36. package/src/version.ts +1 -1
@@ -79,6 +79,28 @@ export class ApprovalsResource {
79
79
  *
80
80
  * Read `finalized` with `applyError`: a vote can finalize a request AND
81
81
  * fail to apply it, and then the money has not moved.
82
+ *
83
+ * On a transfer request the approve that completes the threshold EXECUTES
84
+ * the transfer inside this call, and `status` is `APPROVED` whatever
85
+ * happened to the transfer:
86
+ *
87
+ * finalized, no applyError — executed by this call;
88
+ * applyError — `TRANSFER_EXECUTION_FAILED`, not executed
89
+ * (usually `failed`, reserve returned);
90
+ * not finalized, no applyError — the outcome is NOT established by this
91
+ * answer: the signing service gave no
92
+ * definite answer (the transaction may
93
+ * have left; an administrator's
94
+ * reconciliation settles it), another call
95
+ * is executing the transfer, or the
96
+ * execution broke off. Read the outcome
97
+ * from the transfer (`transfers.get`), and
98
+ * never resubmit it.
99
+ *
100
+ * Repeating the same decision on a request that is still open finishes what
101
+ * an earlier call left undone (it recorded the vote and broke off) — a veto,
102
+ * or an approval once the threshold is met — instead of 409
103
+ * `ALREADY_VOTED`.
82
104
  */
83
105
  vote(requestId: string, input: VoteBody): Promise<RequestVoteResult> {
84
106
  return this.#http.request<RequestVoteResult>(
@@ -21,7 +21,10 @@ export interface VoteInput {
21
21
  * The result of sending is `Gated`, and that is the main thing to understand
22
22
  * here. The same `{transaction}` body comes back in three situations:
23
23
  *
24
- * applied (201) — executed, the money left;
24
+ * applied (201) — executed, the money left (rarely the status is still
25
+ * `pending` with a `txHash`: it went out, but its
26
+ * accounting was not recorded, and an administrator's
27
+ * reconciliation finishes it — do not send it again);
25
28
  * pending (202) — awaiting signatures, funds RESERVED but not sent;
26
29
  * replayed (200) — a transfer with this `idempotencyKey` already existed,
27
30
  * and this is that transfer as it stands NOW.
@@ -34,7 +37,10 @@ export interface VoteInput {
34
37
  *
35
38
  * confirmed, submitted — it left;
36
39
  * awaiting_approval — waiting for signatures, funds reserved;
37
- * pending — still executing;
40
+ * pending — still executing, or its outcome is unknown
41
+ * (the first answer was 502
42
+ * `TRANSFER_OUTCOME_UNKNOWN`) until an
43
+ * administrator reconciles it;
38
44
  * failed, rejected,
39
45
  * cancelled — it did not leave.
40
46
  */
@@ -53,6 +59,12 @@ export class TransfersResource {
53
59
  * On `outcome: 'replayed'` read `data.transaction.status` before telling
54
60
  * anyone anything — a replay of an attempt that failed, or that is still
55
61
  * waiting for signatures, comes back the same way as one that went out.
62
+ *
63
+ * A thrown 502 `TRANSFER_OUTCOME_UNKNOWN` is not a failure: the signing
64
+ * service gave no definite answer, the transaction may have left, and the
65
+ * transfer stays `pending` with its funds reserved (`details.transactionId`).
66
+ * Retry it only with the SAME key — that returns the transfer without
67
+ * executing it again; a new key can send the money twice.
56
68
  */
57
69
  async send(
58
70
  input: CreateTransferBody,
@@ -72,7 +84,9 @@ export class TransfersResource {
72
84
  /**
73
85
  * One transfer in full. Note the shape: this is the transaction itself, not
74
86
  * the `{ transaction }` wrapper that `send()` returns — and it carries more,
75
- * including `amlLevel`, `approvers`, `usdRate` and `failureReason`.
87
+ * including `amlLevel`, `approvers`, `usdRate` and `failureReason` — the
88
+ * last only on `failed`, `rejected` and `cancelled`, `null` on any other
89
+ * status.
76
90
  */
77
91
  get(transferId: string): Promise<TransactionDetail> {
78
92
  return this.#http.request<TransactionDetail>('GET', `${this.#base}/${seg(transferId)}`)
@@ -91,11 +105,30 @@ export class TransfersResource {
91
105
  * awaiting_approval — counted, more signatures still needed;
92
106
  * rejected — a `reject` is a veto, and the reserve is released;
93
107
  * confirmed/failed — this vote completed the threshold, so execution ran
94
- * INSIDE this request (gas, then broadcast, ~10s).
108
+ * INSIDE this request (gas, then broadcast, ~10s);
109
+ * pending — with no `executionError`: the outcome is NOT
110
+ * established by this answer. The signing service
111
+ * gave no definite answer (the transaction may have
112
+ * left; an administrator's reconciliation settles
113
+ * it), another call is executing the transfer, or
114
+ * the execution broke off. Re-read the transfer:
115
+ * `confirmed`/`failed` is the outcome, `pending` for
116
+ * over 10 minutes by `updatedAt` is waiting for
117
+ * reconciliation. Never send it again.
95
118
  *
96
119
  * `failed` means the money is back: execution broke after approval and the
97
120
  * reserve was released, with the reason in `executionError`. Treating the
98
- * call as "approved, done" hides both the success and that failure.
121
+ * call as "approved, done" hides both the success and that failure. The
122
+ * exception is a `failed` transfer that has a `txHash`: it went out after
123
+ * reconciliation had already returned the reserve, and an administrator has
124
+ * to correct the ledger. `executionError` beside `rejected` or `cancelled`
125
+ * means the transfer was no longer waiting for signatures when approved,
126
+ * and nothing was executed.
127
+ *
128
+ * Repeating the same decision while the transfer is still waiting finishes
129
+ * what an earlier call left undone (it recorded the vote and broke off) — a
130
+ * veto, or execution once the threshold is met — instead of 409
131
+ * `ALREADY_VOTED`.
99
132
  */
100
133
  vote(transferId: string, input: VoteInput): Promise<VoteResult> {
101
134
  return this.#http.request<VoteResult>(
@@ -124,19 +157,34 @@ export class TransfersResource {
124
157
  }
125
158
 
126
159
  /**
127
- * Settles a transfer stuck in `pending` — the case where the worker died
128
- * mid-execution, so cancelling does not apply. Administrators only.
160
+ * Settles a transfer nothing else can close. Administrators only.
161
+ *
162
+ * pending — execution died, or its outcome is unknown (the
163
+ * send answered 502 `TRANSFER_OUTCOME_UNKNOWN`);
164
+ * awaiting_approval — with no live approval request to vote on;
165
+ * failed, rejected,
166
+ * cancelled — closed, but the reserve is still held: it is
167
+ * returned, and the status stays.
168
+ *
169
+ * A pending transfer is decided by the HASH: send `txHash` and it is driven
170
+ * to `confirmed`; send none and the reserve is returned (`failed`). Sending
171
+ * none is YOUR statement that nothing was broadcast — the server does not
172
+ * check it, so look on the chain first: returning the reserve of a
173
+ * transaction that did go out creates money. If the transfer already holds
174
+ * a hash from the signing service, only that hash, sent explicitly, settles
175
+ * it — 409 `TRANSFER_BROADCAST` without one, `TXHASH_MISMATCH` with another,
176
+ * the saved hash in `details.txHash`. The other two cases never executed
177
+ * and take no hash.
129
178
  *
130
- * The decision is made by the HASH: send `txHash` and the transfer is
131
- * driven to `confirmed`, because the signing service did put it on the
132
- * chain; send none and the reserve is returned, because there was no
133
- * broadcast. A FRESH pending transfer is refused on purpose — while
134
- * execution may still be in flight, intervening risks a SECOND broadcast,
135
- * which costs more than waiting.
179
+ * A FRESH transfer is refused on purpose — while execution may still be in
180
+ * flight, intervening risks a SECOND broadcast, which costs more than
181
+ * waiting.
136
182
  *
137
- * Pass `fee` along with the hash if you know it: this is the only moment
138
- * it can be recorded on a transfer settled this way, and it stays null
139
- * otherwise. The answer says which way it went — `confirmed` or `failed`.
183
+ * Pass `fee` along with the hash if you know it: this is the only moment it
184
+ * can be recorded on a transfer settled this way; otherwise it stays as it
185
+ * is, null unless the signing service reported one. The answer says which
186
+ * way it went — `confirmed`, `failed`, or the unchanged `rejected` /
187
+ * `cancelled` of a closed transfer.
140
188
  */
141
189
  reconcile(
142
190
  transferId: string,
package/src/version.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** SDK version, sent in the `user-agent` header. */
2
- export const SDK_VERSION = '0.2.1'
2
+ export const SDK_VERSION = '0.2.3'
3
3
 
4
4
  /** Default API base URL. */
5
5
  export const DEFAULT_BASE_URL = 'https://policy-engine-rest.ezig.workers.dev'