merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit ed83bf53a07ba09d174a7bc6472ea69260eb96ff
parent c0a46c7de723a5d8a7b651774468da9d06a56ada
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed,  3 Jun 2026 00:44:28 +0200

-fix

Diffstat:
Msrc/backenddb/example-statistics-0001.sql | 11++++-------
Msrc/backenddb/sql-schema/merchant-0036-copy.sql.fragment | 84++++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 46 insertions(+), 49 deletions(-)

diff --git a/src/backenddb/example-statistics-0001.sql b/src/backenddb/example-statistics-0001.sql @@ -33,8 +33,7 @@ SET search_path TO example_statistics; -- Setup statistic: what do we want to track for 'deposits'? -- (Note: this is basically the one "manual" step we might not keep hard-coded) --- FIXME: wrong: per-instance SCHEMA table now! -INSERT INTO merchant.merchant_statistic_bucket_meta +INSERT INTO merchant_statistic_bucket_meta (slug ,description ,stype @@ -48,8 +47,7 @@ VALUES ,ARRAY[120, 120, 48, 95, 36, 40, 100] -- track last 120 s, 120 minutes, 48 hours, 95 days, 36 months, 40 quarters & 10 years ); --- FIXME: wrong: per-instance SCHEMA table now! -INSERT INTO merchant.merchant_statistic_interval_meta +INSERT INTO merchant_statistic_interval_meta (slug ,description ,stype @@ -68,8 +66,7 @@ VALUES -- Setup statistic -- (Note: this is basically the one "manual" step we might not keep hard-coded) --- FIXME: wrong: per-instance SCHEMA table now! -INSERT INTO merchant.merchant_statistic_bucket_meta +INSERT INTO merchant_statistic_bucket_meta (slug ,description ,stype @@ -104,7 +101,7 @@ END $$; -- Whenever inventory changes, call our trigger to bump statistics CREATE TRIGGER merchant_products_on_sold AFTER UPDATE - ON merchant.merchant_inventory + ON merchant_inventory FOR EACH ROW EXECUTE FUNCTION merchant_products_sold_statistics_trigger(); -- This is for now just an example for how to use the API. --- END EXAMPLE diff --git a/src/backenddb/sql-schema/merchant-0036-copy.sql.fragment b/src/backenddb/sql-schema/merchant-0036-copy.sql.fragment @@ -17,7 +17,7 @@ -- ---------------- direct merchant_serial (no JOIN) -------------- - EXECUTE format('INSERT INTO %I.merchant_accounts' + EXECUTE FORMAT('INSERT INTO %I.merchant_accounts' || ' (account_serial, h_wire, salt, credit_facade_url,' || ' credit_facade_credentials, last_bank_serial, payto_uri,' || ' active, extra_wire_subject_metadata)' @@ -28,14 +28,14 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_categories' + EXECUTE FORMAT('INSERT INTO %I.merchant_categories' || ' (category_serial, category_name, category_name_i18n)' || ' SELECT category_serial, category_name, category_name_i18n' || ' FROM merchant.merchant_categories' || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_contract_terms' + EXECUTE FORMAT('INSERT INTO %I.merchant_contract_terms' || ' (order_serial, order_id, contract_terms, wallet_data,' || ' h_contract_terms, creation_time, pay_deadline, refund_deadline,' || ' paid, wired, fulfillment_url, session_id, pos_key, pos_algorithm,' @@ -48,7 +48,7 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_custom_units' + EXECUTE FORMAT('INSERT INTO %I.merchant_custom_units' || ' (unit_serial, unit, unit_name_long, unit_name_short,' || ' unit_name_long_i18n, unit_name_short_i18n,' || ' unit_allow_fraction, unit_precision_level, unit_active)' @@ -61,7 +61,7 @@ -- merchant_donau_instances: source filter column is named -- merchant_instance_serial (not merchant_serial). - EXECUTE format('INSERT INTO %I.merchant_donau_instances' + EXECUTE FORMAT('INSERT INTO %I.merchant_donau_instances' || ' (donau_instances_serial, donau_url, charity_name, charity_id,' || ' charity_max_per_year, charity_receipts_to_date, current_year)' || ' SELECT donau_instances_serial, donau_url, charity_name, charity_id,' @@ -72,7 +72,7 @@ -- merchant_login_tokens: target `serial` column is GENERATED ALWAYS -- → must use OVERRIDING SYSTEM VALUE to preserve serial values. - EXECUTE format('INSERT INTO %I.merchant_login_tokens' + EXECUTE FORMAT('INSERT INTO %I.merchant_login_tokens' || ' (token, creation_time, expiration_time, validity_scope,' || ' description, serial)' || ' OVERRIDING SYSTEM VALUE' @@ -82,21 +82,21 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_money_pots' + EXECUTE FORMAT('INSERT INTO %I.merchant_money_pots' || ' (money_pot_serial, money_pot_name, money_pot_description, pot_totals)' || ' SELECT money_pot_serial, money_pot_name, money_pot_description, pot_totals' || ' FROM merchant.merchant_money_pots' || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_otp_devices' + EXECUTE FORMAT('INSERT INTO %I.merchant_otp_devices' || ' (otp_serial, otp_id, otp_description, otp_key, otp_algorithm, otp_ctr)' || ' SELECT otp_serial, otp_id, otp_description, otp_key, otp_algorithm, otp_ctr' || ' FROM merchant.merchant_otp_devices' || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_orders' + EXECUTE FORMAT('INSERT INTO %I.merchant_orders' || ' (order_serial, order_id, claim_token, h_post_data, pay_deadline,' || ' creation_time, contract_terms, pos_key, pos_algorithm,' || ' fulfillment_url, session_id)' @@ -107,7 +107,7 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_product_groups' + EXECUTE FORMAT('INSERT INTO %I.merchant_product_groups' || ' (product_group_serial, product_group_name, product_group_description)' || ' SELECT product_group_serial, product_group_name, product_group_description' || ' FROM merchant.merchant_product_groups' @@ -116,7 +116,7 @@ -- merchant_inventory references merchant_product_groups and merchant_money_pots -- (already copied above). - EXECUTE format('INSERT INTO %I.merchant_inventory' + EXECUTE FORMAT('INSERT INTO %I.merchant_inventory' || ' (product_serial, product_id, description, description_i18n,' || ' unit, image, taxes, total_stock, total_sold, total_lost,' || ' address, next_restock, minimum_age, product_name, image_hash,' @@ -133,7 +133,7 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_reports' + EXECUTE FORMAT('INSERT INTO %I.merchant_reports' || ' (report_serial, report_program_section, report_description,' || ' mime_type, report_token, data_source, target_address,' || ' frequency, frequency_shift, next_transmission,' @@ -147,7 +147,7 @@ USING rec.merchant_serial; -- merchant_template references merchant_otp_devices (already copied). - EXECUTE format('INSERT INTO %I.merchant_template' + EXECUTE FORMAT('INSERT INTO %I.merchant_template' || ' (template_serial, template_id, template_description,' || ' otp_device_id, template_contract, editable_defaults)' || ' SELECT template_serial, template_id, template_description,' @@ -156,7 +156,7 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_token_families' + EXECUTE FORMAT('INSERT INTO %I.merchant_token_families' || ' (token_family_serial, slug, name, description, description_i18n,' || ' valid_after, valid_before, duration, kind, issued, used,' || ' validity_granularity, start_offset, cipher_choice, extra_data)' @@ -167,7 +167,7 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_webhook' + EXECUTE FORMAT('INSERT INTO %I.merchant_webhook' || ' (webhook_serial, webhook_id, event_type, url, http_method,' || ' header_template, body_template)' || ' SELECT webhook_serial, webhook_id, event_type, url, http_method,' @@ -177,7 +177,7 @@ USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_builtin_unit_overrides' + EXECUTE FORMAT('INSERT INTO %I.merchant_builtin_unit_overrides' || ' (builtin_unit_serial, override_allow_fraction,' || ' override_precision_level, override_active)' || ' SELECT builtin_unit_serial, override_allow_fraction,' @@ -187,21 +187,21 @@ USING rec.merchant_serial; -- ---------------- statistics: meta tables are GLOBAL ------------ - -- Copied unfiltered (every instance gets a full slug catalog). + -- Copied unfiltered (every instance gets a full stats catalog). - EXECUTE format('INSERT INTO %I.merchant_statistic_bucket_meta' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_bucket_meta' || ' (bmeta_serial_id, slug, description, stype, ranges, ages)' || ' SELECT bmeta_serial_id, slug, description, stype, ranges, ages' || ' FROM merchant.merchant_statistic_bucket_meta', s); - EXECUTE format('INSERT INTO %I.merchant_statistic_interval_meta' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_interval_meta' || ' (imeta_serial_id, slug, description, stype, ranges, precisions)' || ' SELECT imeta_serial_id, slug, description, stype, ranges, precisions' || ' FROM merchant.merchant_statistic_interval_meta', s); -- ---------------- statistics: per-instance event/bucket tables -- - EXECUTE format('INSERT INTO %I.merchant_statistic_amount_event' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_amount_event' || ' (aevent_serial_id, imeta_serial_id, slot,' || ' delta_curr, delta_value, delta_frac)' || ' SELECT aevent_serial_id, imeta_serial_id, slot,' @@ -210,14 +210,14 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_statistic_counter_event' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_counter_event' || ' (nevent_serial_id, imeta_serial_id, slot, delta)' || ' SELECT nevent_serial_id, imeta_serial_id, slot, delta' || ' FROM merchant.merchant_statistic_counter_event' || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_statistic_bucket_amount' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_bucket_amount' || ' (bmeta_serial_id, bucket_start, bucket_range, curr,' || ' cumulative_value, cumulative_frac)' || ' SELECT bmeta_serial_id, bucket_start, bucket_range, curr,' @@ -226,14 +226,14 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_statistic_bucket_counter' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_bucket_counter' || ' (bmeta_serial_id, bucket_start, bucket_range, cumulative_number)' || ' SELECT bmeta_serial_id, bucket_start, bucket_range, cumulative_number' || ' FROM merchant.merchant_statistic_bucket_counter' || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_statistic_interval_amount' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_interval_amount' || ' (imeta_serial_id, event_delimiter, range, curr,' || ' cumulative_value, cumulative_frac)' || ' SELECT imeta_serial_id, event_delimiter, range, curr,' @@ -242,7 +242,7 @@ || ' WHERE merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_statistic_interval_counter' + EXECUTE FORMAT('INSERT INTO %I.merchant_statistic_interval_counter' || ' (imeta_serial_id, range, event_delimiter, cumulative_number)' || ' SELECT imeta_serial_id, range, event_delimiter, cumulative_number' || ' FROM merchant.merchant_statistic_interval_counter' @@ -251,7 +251,7 @@ -- ---------------- account-linked (JOIN via account_serial) ------ - EXECUTE format('INSERT INTO %I.merchant_kyc' + EXECUTE FORMAT('INSERT INTO %I.merchant_kyc' || ' (kyc_serial_id, kyc_timestamp, kyc_ok, account_serial,' || ' exchange_url, access_token, exchange_http_status,' || ' exchange_ec_code, aml_review, jaccount_limits,' @@ -266,7 +266,7 @@ || ' WHERE a.merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_deposit_confirmations' + EXECUTE FORMAT('INSERT INTO %I.merchant_deposit_confirmations' || ' (deposit_confirmation_serial, order_serial, deposit_timestamp,' || ' exchange_url, total_without_fee, wire_fee, signkey_serial,' || ' exchange_sig, account_serial, wire_transfer_deadline,' @@ -281,7 +281,7 @@ || ' WHERE a.merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_expected_transfers' + EXECUTE FORMAT('INSERT INTO %I.merchant_expected_transfers' || ' (expected_credit_serial, exchange_url, wtid, expected_credit_amount,' || ' wire_fee, account_serial, expected_time, retry_time, last_http_status,' || ' last_ec, last_detail, retry_needed, signkey_serial, exchange_sig,' @@ -296,7 +296,7 @@ || ' WHERE a.merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_transfers' + EXECUTE FORMAT('INSERT INTO %I.merchant_transfers' || ' (credit_serial, exchange_url, wtid, credit_amount, account_serial,' || ' bank_serial_id, expected, execution_time)' || ' SELECT t.credit_serial, t.exchange_url, t.wtid, t.credit_amount, t.account_serial,' @@ -309,7 +309,7 @@ -- ---------------- deposits: deeper join (dc → accounts) --------- - EXECUTE format('INSERT INTO %I.merchant_deposits' + EXECUTE FORMAT('INSERT INTO %I.merchant_deposits' || ' (deposit_serial, coin_offset, deposit_confirmation_serial,' || ' coin_pub, coin_sig, amount_with_fee, deposit_fee, refund_fee,' || ' settlement_retry_needed, settlement_retry_time,' @@ -333,7 +333,7 @@ USING rec.merchant_serial; -- expected_transfer_to_coin: deposit_serial → deposits → dc → accounts. - EXECUTE format('INSERT INTO %I.merchant_expected_transfer_to_coin' + EXECUTE FORMAT('INSERT INTO %I.merchant_expected_transfer_to_coin' || ' (deposit_serial, expected_credit_serial, offset_in_exchange_list,' || ' exchange_deposit_value, exchange_deposit_fee)' || ' SELECT ettc.deposit_serial, ettc.expected_credit_serial, ettc.offset_in_exchange_list,' @@ -349,7 +349,7 @@ USING rec.merchant_serial; -- transfer_signatures: expected_credit_serial → expected_transfers → accounts. - EXECUTE format('INSERT INTO %I.merchant_transfer_signatures' + EXECUTE FORMAT('INSERT INTO %I.merchant_transfer_signatures' || ' (expected_credit_serial, signkey_serial, wire_fee, credit_amount,' || ' execution_time, exchange_sig)' || ' SELECT ts.expected_credit_serial, ts.signkey_serial, ts.wire_fee, ts.credit_amount,' @@ -364,7 +364,7 @@ -- ---------------- order/contract-linked (JOIN via order_serial) --- - EXECUTE format('INSERT INTO %I.merchant_refunds' + EXECUTE FORMAT('INSERT INTO %I.merchant_refunds' || ' (refund_serial, order_serial, rtransaction_id, refund_timestamp,' || ' coin_pub, reason, refund_amount)' || ' SELECT r.refund_serial, r.order_serial, r.rtransaction_id, r.refund_timestamp,' @@ -375,7 +375,7 @@ || ' WHERE ct.merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_refund_proofs' + EXECUTE FORMAT('INSERT INTO %I.merchant_refund_proofs' || ' (refund_serial, exchange_sig, signkey_serial)' || ' SELECT rp.refund_serial, rp.exchange_sig, rp.signkey_serial' || ' FROM merchant.merchant_refund_proofs rp' @@ -386,7 +386,7 @@ || ' WHERE ct.merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_order_token_blinded_sigs' + EXECUTE FORMAT('INSERT INTO %I.merchant_order_token_blinded_sigs' || ' (order_token_bs_serial, order_serial, token_index,' || ' token_blinded_signature, token_hash)' || ' SELECT otbs.order_token_bs_serial, otbs.order_serial, otbs.token_index,' @@ -398,7 +398,7 @@ USING rec.merchant_serial; -- unclaim_signatures: linked via h_contract_terms. - EXECUTE format('INSERT INTO %I.merchant_unclaim_signatures' + EXECUTE FORMAT('INSERT INTO %I.merchant_unclaim_signatures' || ' (unclaim_serial, h_contract_terms, unclaim_sig, expiration_time)' || ' SELECT us.unclaim_serial, us.h_contract_terms, us.unclaim_sig, us.expiration_time' || ' FROM merchant.merchant_unclaim_signatures us' @@ -408,7 +408,7 @@ USING rec.merchant_serial; -- order_locks: order_serial → contract_terms. - EXECUTE format('INSERT INTO %I.merchant_order_locks' + EXECUTE FORMAT('INSERT INTO %I.merchant_order_locks' || ' (product_serial, total_locked, order_serial, total_locked_frac)' || ' SELECT ol.product_serial, ol.total_locked, ol.order_serial, ol.total_locked_frac' || ' FROM merchant.merchant_order_locks ol' @@ -418,7 +418,7 @@ USING rec.merchant_serial; -- inventory_locks: product_serial → inventory. - EXECUTE format('INSERT INTO %I.merchant_inventory_locks' + EXECUTE FORMAT('INSERT INTO %I.merchant_inventory_locks' || ' (product_serial, lock_uuid, total_locked, expiration, total_locked_frac)' || ' SELECT il.product_serial, il.lock_uuid, il.total_locked, il.expiration, il.total_locked_frac' || ' FROM merchant.merchant_inventory_locks il' @@ -428,7 +428,7 @@ USING rec.merchant_serial; -- product_categories: junction; pivot on product_serial → inventory. - EXECUTE format('INSERT INTO %I.merchant_product_categories' + EXECUTE FORMAT('INSERT INTO %I.merchant_product_categories' || ' (category_serial, product_serial)' || ' SELECT pc.category_serial, pc.product_serial' || ' FROM merchant.merchant_product_categories pc' @@ -439,7 +439,7 @@ -- ---------------- token chain (token_families → keys → tokens) -- - EXECUTE format('INSERT INTO %I.merchant_token_family_keys' + EXECUTE FORMAT('INSERT INTO %I.merchant_token_family_keys' || ' (token_family_key_serial, token_family_serial, pub, h_pub,' || ' priv, cipher, signature_validity_start, signature_validity_end,' || ' private_key_deleted_at, private_key_created_at)' @@ -452,7 +452,7 @@ || ' WHERE tf.merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_issued_tokens' + EXECUTE FORMAT('INSERT INTO %I.merchant_issued_tokens' || ' (issued_token_serial, h_contract_terms, token_family_key_serial, blind_sig)' || ' SELECT it.issued_token_serial, it.h_contract_terms, it.token_family_key_serial, it.blind_sig' || ' FROM merchant.merchant_issued_tokens it' @@ -463,7 +463,7 @@ || ' WHERE tf.merchant_serial = $1', s) USING rec.merchant_serial; - EXECUTE format('INSERT INTO %I.merchant_used_tokens' + EXECUTE FORMAT('INSERT INTO %I.merchant_used_tokens' || ' (spent_token_serial, h_contract_terms, token_family_key_serial,' || ' token_pub, token_sig, blind_sig)' || ' SELECT ut.spent_token_serial, ut.h_contract_terms, ut.token_family_key_serial,'