@dvmkit/sdk 0.4.0-rc.1 → 0.6.0-rc.1
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 +100 -0
- package/dist/{chunk-TXX4GOUB.js → chunk-7ZUKL4IV.js} +1 -1
- package/dist/chunk-AFV77S4C.js +258 -0
- package/dist/{chunk-2VGWYG4P.js → chunk-B2IROPQF.js} +446 -81
- package/dist/chunk-BQJIFRAZ.js +36 -0
- package/dist/{chunk-PB4FYZET.js → chunk-EQLA4FFY.js} +54 -4
- package/dist/{chunk-74PUEZJ4.js → chunk-GFY5FRX3.js} +1 -1
- package/dist/{chunk-O3QDFPKM.js → chunk-HCLVYZUZ.js} +2 -2
- package/dist/{chunk-K2YX2VRA.js → chunk-HHBDBMEO.js} +170 -43
- package/dist/{chunk-O5AT6S5T.js → chunk-IV6Q7NRW.js} +25 -195
- package/dist/{chunk-W2EQGDF5.js → chunk-LE74UEV7.js} +49 -8
- package/dist/{chunk-CE7XEHYC.js → chunk-N5RZ5HVB.js} +1 -1
- package/dist/chunk-OFVV37XC.js +57 -0
- package/dist/{chunk-5LR6P7WN.js → chunk-OQA7IHI4.js} +133 -213
- package/dist/{chunk-3MHE725Z.js → chunk-PAIM66YA.js} +90 -1
- package/dist/{chunk-6DOGTAHA.js → chunk-QR2EF2NI.js} +9 -43
- package/dist/{chunk-KXZUCCEY.js → chunk-RCM3P2HE.js} +5 -56
- package/dist/{chunk-R4DQZFAL.js → chunk-UOCZXO2Z.js} +3 -3
- package/dist/content-retention-BTGSQRfP.d.ts +78 -0
- package/dist/{credit-menu-B8_p_vUz.d.ts → credit-menu-BAsrRu3z.d.ts} +98 -5
- package/dist/{fx-DuaYHvVn.d.ts → fx-BgDmyTdd.d.ts} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -3
- package/dist/internal/caller.d.ts +90 -22
- package/dist/internal/caller.js +40 -40
- package/dist/internal/index.js +1 -1
- package/dist/internal/server.d.ts +8 -99
- package/dist/internal/server.js +15 -11
- package/dist/{job-store-D6Rjj5Oi.d.ts → job-store-BVeF5_Jq.d.ts} +1 -1
- package/dist/{lightning-backend-BaeCPmx7.d.ts → lightning-backend-40fIzz1W.d.ts} +1 -1
- package/dist/{postgres-consumed-credential-store-CUQJKRSL.js → postgres-consumed-credential-store-BUVCAPLS.js} +13 -0
- package/dist/{postgres-job-store-VLXLWXUQ.js → postgres-job-store-VHLQBJZC.js} +3 -1
- package/dist/server/index.d.ts +28 -10
- package/dist/server/index.js +24 -10
- package/dist/{step-cache-Bi43A0JN.d.ts → step-cache-CPdH1hei.d.ts} +3 -3
- package/dist/{tempo-lifecycle-OTHV757Y.js → tempo-lifecycle-ZBBLFBMH.js} +5 -4
- package/dist/{tempo-wallet-32JWQZKQ.js → tempo-wallet-B5XXV3YH.js} +1 -1
- package/dist/testing/index.d.ts +9 -2
- package/dist/testing/index.js +6 -3
- package/dist/{usd-AZPVq4eU.d.ts → usd-AWlrwlM5.d.ts} +1 -1
- package/dist/{x402-CEDHGZDI.js → x402-R6HPBY5D.js} +5 -4
- package/package.json +3 -2
- package/recipes/postgres/financial-export-v1.sql +137 -0
|
@@ -10,12 +10,12 @@ import {
|
|
|
10
10
|
saveX402Wallet,
|
|
11
11
|
tryX402Payment,
|
|
12
12
|
x402WrongAssetHint
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-LE74UEV7.js";
|
|
14
|
+
import "./chunk-B2IROPQF.js";
|
|
15
15
|
import "./chunk-MZRJR2CW.js";
|
|
16
16
|
import {
|
|
17
17
|
verifyX402Payment
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-7ZUKL4IV.js";
|
|
19
19
|
import "./chunk-PLG4XER6.js";
|
|
20
20
|
import {
|
|
21
21
|
X402_DEFAULT_FACILITATOR,
|
|
@@ -36,8 +36,9 @@ import {
|
|
|
36
36
|
usdcContractByCaip2,
|
|
37
37
|
x402NetworkToCaip2
|
|
38
38
|
} from "./chunk-IWQHUSMO.js";
|
|
39
|
-
import "./chunk-
|
|
39
|
+
import "./chunk-PAIM66YA.js";
|
|
40
40
|
import "./chunk-CZULM42S.js";
|
|
41
|
+
import "./chunk-OFVV37XC.js";
|
|
41
42
|
import "./chunk-66HGCPBU.js";
|
|
42
43
|
import "./chunk-FUJ36YDV.js";
|
|
43
44
|
import "./chunk-AT6V3SY7.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dvmkit/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-rc.1",
|
|
4
4
|
"description": "SDK for building accountless, pay-per-use Digital Vending Machines",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
},
|
|
37
37
|
"files": [
|
|
38
38
|
"dist",
|
|
39
|
-
"NOTICE"
|
|
39
|
+
"NOTICE",
|
|
40
|
+
"recipes"
|
|
40
41
|
],
|
|
41
42
|
"engines": {
|
|
42
43
|
"node": ">=22"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
-- Run with psql -X -q -t -A -v ON_ERROR_STOP=1 -f financial-export-v1.sql > financial-evidence.json
|
|
2
|
+
-- The transaction gives every table one consistent snapshot. Optional rail tables
|
|
3
|
+
-- absent from this service are empty arrays. Keep this file with the export.
|
|
4
|
+
-- Receipts are signed over every field. Reject unsupported shapes instead of
|
|
5
|
+
-- removing signed extensions and silently producing unverifiable evidence.
|
|
6
|
+
CREATE OR REPLACE FUNCTION pg_temp.receipt_v1(value jsonb) RETURNS jsonb LANGUAGE plpgsql IMMUTABLE AS $$
|
|
7
|
+
DECLARE allowed text[]; nested_allowed text[]; item record; nested_item record;
|
|
8
|
+
BEGIN
|
|
9
|
+
IF value IS NULL OR value = 'null'::jsonb THEN RETURN value; END IF;
|
|
10
|
+
IF jsonb_typeof(value) <> 'object' OR value->'v' IS DISTINCT FROM '1'::jsonb THEN
|
|
11
|
+
RAISE EXCEPTION 'financial export v1: unsupported receipt version or shape';
|
|
12
|
+
END IF;
|
|
13
|
+
CASE value->>'kind'
|
|
14
|
+
WHEN 'credit_funding' THEN allowed := ARRAY['v','kind','credit_id','fund_id','funded_micro','balance_after_micro','ledger_seq','issued_at','caller_pubkey','dvm_id','dvm','receipt_pubkey','signature'];
|
|
15
|
+
WHEN 'credit_drain' THEN allowed := ARRAY['v','kind','credit_id','drain_id','event','method','amount_micro','balance_after_micro','ledger_seq','issued_at','caller_pubkey','dvm_id','dvm','receipt_pubkey','signature'];
|
|
16
|
+
ELSE
|
|
17
|
+
IF value ? 'kind' THEN RAISE EXCEPTION 'financial export v1: unsupported receipt kind'; END IF;
|
|
18
|
+
allowed := ARRAY['v','job_id','dvm_id','dvm','capability','outcome','reason','ended_by','seq','issued_at','requester_pubkey','result_hash','receipt_pubkey','signature','paid','timing','credit'];
|
|
19
|
+
END CASE;
|
|
20
|
+
FOR item IN SELECT key,val FROM jsonb_each(value) AS e(key,val) LOOP
|
|
21
|
+
IF NOT item.key = ANY(allowed) THEN
|
|
22
|
+
RAISE EXCEPTION 'financial export v1: unsupported signed receipt extension';
|
|
23
|
+
END IF;
|
|
24
|
+
IF item.key = ANY(ARRAY['paid','timing','credit']) THEN
|
|
25
|
+
IF jsonb_typeof(item.val) <> 'object' THEN
|
|
26
|
+
RAISE EXCEPTION 'financial export v1: unsupported receipt block';
|
|
27
|
+
END IF;
|
|
28
|
+
nested_allowed := CASE item.key
|
|
29
|
+
WHEN 'paid' THEN ARRAY['msats','rail','native_amount','native_asset','tx_hash','mint']
|
|
30
|
+
WHEN 'timing' THEN ARRAY['accepted_at_ms','terminal_at_ms','caller_wait_ms']
|
|
31
|
+
WHEN 'credit' THEN ARRAY['credit_id','draw_id','amount','balance_after','ledger_seq'] END;
|
|
32
|
+
FOR nested_item IN SELECT key,val FROM jsonb_each(item.val) AS n(key,val) LOOP
|
|
33
|
+
IF NOT nested_item.key = ANY(nested_allowed) OR jsonb_typeof(nested_item.val) = ANY(ARRAY['object','array']) THEN
|
|
34
|
+
RAISE EXCEPTION 'financial export v1: unsupported signed receipt block extension';
|
|
35
|
+
END IF;
|
|
36
|
+
END LOOP;
|
|
37
|
+
ELSIF jsonb_typeof(item.val) = ANY(ARRAY['object','array']) THEN
|
|
38
|
+
RAISE EXCEPTION 'financial export v1: unsupported receipt field shape';
|
|
39
|
+
END IF;
|
|
40
|
+
END LOOP;
|
|
41
|
+
RETURN value;
|
|
42
|
+
END
|
|
43
|
+
$$;
|
|
44
|
+
-- Unsigned evidence uses explicit scalar projections. Objects/arrays in scalar
|
|
45
|
+
-- positions are excluded, including inside the supported nested financial blocks.
|
|
46
|
+
CREATE OR REPLACE FUNCTION pg_temp.scalars_v1(value jsonb, strings text[], numbers text[], booleans text[] DEFAULT ARRAY[]::text[]) RETURNS jsonb LANGUAGE sql IMMUTABLE AS $$
|
|
47
|
+
SELECT CASE WHEN jsonb_typeof(value) <> 'object' THEN NULL ELSE
|
|
48
|
+
(SELECT COALESCE(jsonb_object_agg(key,val), '{}'::jsonb) FROM jsonb_each(value) AS e(key,val)
|
|
49
|
+
WHERE (key=ANY(strings) AND jsonb_typeof(val) IN ('string','null'))
|
|
50
|
+
OR (key=ANY(numbers) AND (jsonb_typeof(val) IN ('number','null') OR (jsonb_typeof(val)='string' AND val #>> '{}' ~ '^-?[0-9]+$')))
|
|
51
|
+
OR (key=ANY(booleans) AND jsonb_typeof(val) IN ('boolean','null'))) END
|
|
52
|
+
$$;
|
|
53
|
+
CREATE OR REPLACE FUNCTION pg_temp.settlement_v1(value jsonb) RETURNS jsonb LANGUAGE sql IMMUTABLE AS $$
|
|
54
|
+
SELECT pg_temp.scalars_v1(value,
|
|
55
|
+
ARRAY['tx_hash','transaction','channel_id','network','repair_kind','payer'],
|
|
56
|
+
ARRAY['settledAmount','settled_amount','amount','refunded_native','debited_native','surplus_native'], ARRAY['success','repaired'])
|
|
57
|
+
$$;
|
|
58
|
+
CREATE OR REPLACE FUNCTION pg_temp.fulfilment_v1(value jsonb) RETURNS jsonb LANGUAGE sql IMMUTABLE AS $$
|
|
59
|
+
SELECT pg_temp.scalars_v1(value, ARRAY['source','mintUrl','quoteId'], ARRAY['faceSats','reserveSats','invoiceMsats','routingFeeMsats'])
|
|
60
|
+
$$;
|
|
61
|
+
CREATE OR REPLACE FUNCTION pg_temp.lot_debits_v1(value jsonb) RETURNS jsonb LANGUAGE sql IMMUTABLE AS $$
|
|
62
|
+
SELECT CASE WHEN jsonb_typeof(value) <> 'array' THEN NULL ELSE
|
|
63
|
+
(SELECT COALESCE(jsonb_agg(pg_temp.scalars_v1(item, ARRAY['lotId'], ARRAY['micro','sats'])), '[]'::jsonb)
|
|
64
|
+
FROM jsonb_array_elements(value) item WHERE jsonb_typeof(item)='object') END
|
|
65
|
+
$$;
|
|
66
|
+
CREATE OR REPLACE FUNCTION pg_temp.effect_v1(value jsonb) RETURNS jsonb LANGUAGE sql IMMUTABLE AS $$
|
|
67
|
+
SELECT pg_temp.scalars_v1(value, ARRAY['callerId','dvmId','jobId'],
|
|
68
|
+
ARRAY['requiredMsats','paidMsats','fundedMicro','nativeAmount','topUpCapMicro'], ARRAY['drawBasis','askSatisfied','midJob'])
|
|
69
|
+
|| jsonb_strip_nulls(jsonb_build_object(
|
|
70
|
+
'priceFiat', pg_temp.scalars_v1(value->'priceFiat', ARRAY['currency'], ARRAY['amountMicro']),
|
|
71
|
+
'fundOnly', pg_temp.scalars_v1(value->'fundOnly', ARRAY['creditId','fundId'], ARRAY[]::text[]),
|
|
72
|
+
'topUp', pg_temp.scalars_v1(value->'topUp', ARRAY['creditId','drawId'], ARRAY[]::text[]),
|
|
73
|
+
'creditEnvelope', pg_temp.scalars_v1(value->'creditEnvelope', ARRAY['creditId','drawId'], ARRAY[]::text[])))
|
|
74
|
+
$$;
|
|
75
|
+
CREATE OR REPLACE FUNCTION pg_temp.channel_config_v1(value jsonb) RETURNS jsonb LANGUAGE sql IMMUTABLE AS $$
|
|
76
|
+
SELECT pg_temp.scalars_v1(value, ARRAY['payer','payerAuthorizer','receiver','receiverAuthorizer'], ARRAY['withdrawDelay'])
|
|
77
|
+
|| CASE WHEN value->>'token' ~ '^0x[0-9a-fA-F]{40}$' THEN jsonb_build_object('token',value->'token') ELSE '{}'::jsonb END
|
|
78
|
+
$$;
|
|
79
|
+
CREATE OR REPLACE FUNCTION pg_temp.tempo_state_v1(value jsonb) RETURNS jsonb LANGUAGE plpgsql IMMUTABLE AS $$
|
|
80
|
+
DECLARE state jsonb; amounts jsonb;
|
|
81
|
+
BEGIN
|
|
82
|
+
IF value IS NULL OR value='null'::jsonb THEN RETURN NULL; END IF;
|
|
83
|
+
IF jsonb_typeof(value)<>'string' THEN RETURN NULL; END IF;
|
|
84
|
+
BEGIN state := (value #>> '{}')::jsonb;
|
|
85
|
+
EXCEPTION WHEN OTHERS THEN RAISE EXCEPTION 'financial export v1: unsupported Tempo state'; END;
|
|
86
|
+
IF jsonb_typeof(state)<>'object' THEN RETURN NULL; END IF;
|
|
87
|
+
-- Normalize the store's tagged bigints without retaining vouchers or signatures.
|
|
88
|
+
SELECT COALESCE(jsonb_object_agg(key, regexp_replace(val #>> '{}', '#__bigint$', '')), '{}'::jsonb) INTO amounts
|
|
89
|
+
FROM jsonb_each(state) AS e(key,val)
|
|
90
|
+
WHERE key=ANY(ARRAY['deposit','spent','settledOnChain','highestVoucherAmount','closeRequestedAt'])
|
|
91
|
+
AND jsonb_typeof(val) IN ('number','string') AND val #>> '{}' ~ '^[0-9]+(#__bigint)?$';
|
|
92
|
+
RETURN pg_temp.scalars_v1(state, ARRAY['channelId','escrowContract','payee','payer'], ARRAY['chainId','units'], ARRAY['finalized']) || amounts
|
|
93
|
+
|| CASE WHEN state->>'token' ~ '^0x[0-9a-fA-F]{40}$' THEN jsonb_build_object('token',state->'token') ELSE '{}'::jsonb END;
|
|
94
|
+
END
|
|
95
|
+
$$;
|
|
96
|
+
CREATE OR REPLACE FUNCTION pg_temp.financial_rows_v1(table_name text, columns text[]) RETURNS jsonb LANGUAGE plpgsql AS $$
|
|
97
|
+
DECLARE result jsonb;
|
|
98
|
+
BEGIN
|
|
99
|
+
IF to_regclass(table_name) IS NULL THEN RETURN '[]'::jsonb; END IF;
|
|
100
|
+
EXECUTE format('SELECT COALESCE(jsonb_agg(projected ORDER BY projected::text), ''[]''::jsonb) FROM (
|
|
101
|
+
SELECT (SELECT COALESCE(jsonb_object_agg(key,
|
|
102
|
+
CASE WHEN key=ANY(ARRAY[''sent_ref'',''settle_response'']) THEN pg_temp.settlement_v1(value)
|
|
103
|
+
WHEN key=''fulfilment'' THEN pg_temp.fulfilment_v1(value)
|
|
104
|
+
WHEN key=''lot_debits'' THEN pg_temp.lot_debits_v1(value)
|
|
105
|
+
WHEN key=''state_json'' THEN pg_temp.tempo_state_v1(value)
|
|
106
|
+
WHEN key=''channel_config'' THEN pg_temp.channel_config_v1(value)
|
|
107
|
+
WHEN key=''effect'' THEN pg_temp.effect_v1(value)
|
|
108
|
+
WHEN key=''receipt'' THEN pg_temp.receipt_v1(value)
|
|
109
|
+
WHEN key=''receipts'' THEN (SELECT COALESCE(jsonb_agg(pg_temp.receipt_v1(r)), ''[]''::jsonb) FROM jsonb_array_elements(value) r)
|
|
110
|
+
ELSE CASE WHEN jsonb_typeof(value) NOT IN (''object'',''array'') THEN value ELSE NULL END END), ''{}''::jsonb)
|
|
111
|
+
FROM jsonb_each(to_jsonb(t)) WHERE key=ANY($1)) projected FROM %I t) rows', table_name)
|
|
112
|
+
INTO result USING columns;
|
|
113
|
+
RETURN result;
|
|
114
|
+
END
|
|
115
|
+
$$;
|
|
116
|
+
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY;
|
|
117
|
+
SELECT jsonb_build_object(
|
|
118
|
+
'format', 'dvmkit-financial-evidence', 'version', 1,
|
|
119
|
+
'jobs', pg_temp.financial_rows_v1('jobs', ARRAY['id','dvm_id','request_id','requester_pubkey','capability','status','created_at','last_activity_at','terminal_at_ms','ended_by','receipt','receipt_seq','paid_msats','payment_rail','payment_tx_hash','payment_transaction_hash','native_amount','native_asset','credit_id','draw_id','cost_amount_micro','cost_currency']),
|
|
120
|
+
'credits', pg_temp.financial_rows_v1('credits', ARRAY['credit_id','caller_pubkey','currency','balance_micro','expiry_ms','status','last_ledger_seq','created_at','rail','native_asset','funding_ref','tempo_channel_id','x402_channel_id','msats_remaining','native_remaining']),
|
|
121
|
+
'fundings', pg_temp.financial_rows_v1('credit_fundings', ARRAY['credit_id','fund_id','caller_pubkey','amount_micro','rail','created_at','balance_after_micro','ledger_seq','receipt']),
|
|
122
|
+
'funding_lots', pg_temp.financial_rows_v1('credit_funding_lots', ARRAY['lot_id','credit_id','rail','sats_funded','credited_micro','remaining_micro','funding_ref','created_at']),
|
|
123
|
+
'draws', pg_temp.financial_rows_v1('credit_draws', ARRAY['credit_id','draw_id','job_id','amount_micro','ledger_seq','status','balance_after_micro','created_at','resolved_at','draw_msats','allocated_msats','draw_native','grown_micro']),
|
|
124
|
+
'drains', pg_temp.financial_rows_v1('credit_drains', ARRAY['credit_id','drain_id','method','amount_micro','balance_after_micro','drained_msats','drained_native','owed_sats','ledger_seq','status','receipts','sent_ref','fulfilment','lot_debits','created_at','parked_at','picked_up_at','sent_at','released_at','written_off_at']),
|
|
125
|
+
'invoices', pg_temp.financial_rows_v1('credit_invoices', ARRAY['credit_id','fund_id','caller_pubkey','currency','amount_micro','amount_msats','payment_hash','status','expires_at','created_at','settled_at','reconciled_credit_id','reconciled_fund_id','resolved_at']),
|
|
126
|
+
'expiry_releases', pg_temp.financial_rows_v1('credit_expiry_releases', ARRAY['credit_id','release_id','caller_pubkey','currency','rail','amount_micro','expiry_ms','released_at','reversed_at']),
|
|
127
|
+
'tempo_channels', pg_temp.financial_rows_v1('mpp_tempo_channels', ARRAY['channel_key','state_json','updated_at']),
|
|
128
|
+
'tempo_channel_tombstones', pg_temp.financial_rows_v1('mpp_tempo_channel_tombstones', ARRAY['channel_key','state_json','deleted_at_ms']),
|
|
129
|
+
'tempo_close_intents', pg_temp.financial_rows_v1('mpp_tempo_close_intents', ARRAY['channel_id','drain_id','reference','forecast_pending','updated_at']),
|
|
130
|
+
'x402_channels', pg_temp.financial_rows_v1('x402_batch_channels', ARRAY['channel_id','channel_config','charged_cumulative_amount','signed_max_claimable','balance','total_claimed','withdraw_requested_at','refund_nonce','onchain_synced_at','last_request_timestamp']),
|
|
131
|
+
'x402_channel_tombstones', pg_temp.financial_rows_v1('x402_batch_channel_tombstones', ARRAY['channel_id','charged_cumulative_amount','signed_max_claimable','refund_nonce','deleted_at_ms']),
|
|
132
|
+
'x402_batch_settlements', pg_temp.financial_rows_v1('x402_batch_settlements', ARRAY['settlement_id','channel_id','operation','effect_id','payment_id','status','submission_block','settle_response','created_at','updated_at','resolved_at']),
|
|
133
|
+
'x402_exact_settlements', pg_temp.financial_rows_v1('x402_exact_settlement_intents', ARRAY['dvm_id','intent_id','network','asset','authorizer','recipient','value','status','effect','submission_block','transaction','settle_response','last_outcome','created_at','updated_at','resolved_at']),
|
|
134
|
+
'tempo_losses', pg_temp.financial_rows_v1('tempo_credit_losses', ARRAY['credit_id','channel_id','caller_pubkey','currency','former_balance_micro','settled_on_chain_native','highest_voucher_native','consumed_service_micro','consumed_native','observed_at']),
|
|
135
|
+
'x402_losses', pg_temp.financial_rows_v1('x402_credit_losses', ARRAY['credit_id','channel_id','caller_pubkey','currency','former_balance_micro','channel_balance_native','total_claimed_native','consumed_service_micro','observed_at'])
|
|
136
|
+
);
|
|
137
|
+
ROLLBACK;
|