summaryrefslogtreecommitdiff
path: root/src/backenddb/merchant-0001.sql
diff options
context:
space:
mode:
Diffstat (limited to 'src/backenddb/merchant-0001.sql')
-rw-r--r--src/backenddb/merchant-0001.sql516
1 files changed, 378 insertions, 138 deletions
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index cd4ae9f3..2adb9996 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -1,6 +1,6 @@
--
-- This file is part of TALER
--- Copyright (C) 2014--2022 Taler Systems SA
+-- Copyright (C) 2014--2023 Taler Systems SA
--
-- TALER is free software; you can redistribute it and/or modify it under the
-- terms of the GNU General Public License as published by the Free Software
@@ -14,6 +14,11 @@
-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
--
+-- @file merchant-0001.sql
+-- @brief database schema for the merchant
+-- @author Christian Grothoff
+-- @author Priscilla Huang
+
-- Everything in one big transaction
BEGIN;
@@ -25,6 +30,15 @@ COMMENT ON SCHEMA merchant IS 'taler-merchant data';
SET search_path TO merchant;
+CREATE TYPE taler_amount_currency
+ AS
+ (val INT8
+ ,frac INT4
+ ,curr VARCHAR(12)
+ );
+COMMENT ON TYPE taler_amount_currency
+ IS 'Stores an amount, fraction is in units of 1/100000000 of the base value';
+
---------------- Exchange information ---------------------------
CREATE TABLE IF NOT EXISTS merchant_exchange_wire_fees
@@ -33,12 +47,8 @@ CREATE TABLE IF NOT EXISTS merchant_exchange_wire_fees
,h_wire_method BYTEA NOT NULL CHECK (LENGTH(h_wire_method)=64)
,start_date INT8 NOT NULL
,end_date INT8 NOT NULL
- ,wire_fee_val INT8 NOT NULL
- ,wire_fee_frac INT4 NOT NULL
- ,closing_fee_val INT8 NOT NULL
- ,closing_fee_frac INT4 NOT NULL
- ,wad_fee_val INT8 NOT NULL
- ,wad_fee_frac INT4 NOT NULL
+ ,wire_fee taler_amount_currency NOT NULL
+ ,closing_fee taler_amount_currency NOT NULL
,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
,UNIQUE (master_pub,h_wire_method,start_date)
);
@@ -70,17 +80,17 @@ CREATE TABLE IF NOT EXISTS merchant_instances
,merchant_pub BYTEA NOT NULL UNIQUE CHECK (LENGTH(merchant_pub)=32)
,auth_hash BYTEA CHECK(LENGTH(auth_hash)=64)
,auth_salt BYTEA CHECK(LENGTH(auth_salt)=32)
- ,merchant_id VARCHAR NOT NULL UNIQUE
- ,merchant_name VARCHAR NOT NULL
+ ,merchant_id TEXT NOT NULL UNIQUE
+ ,merchant_name TEXT NOT NULL
+ ,website TEXT
+ ,email TEXT
+ ,logo BYTEA
,address BYTEA NOT NULL
,jurisdiction BYTEA NOT NULL
- ,default_max_deposit_fee_val INT8 NOT NULL
- ,default_max_deposit_fee_frac INT4 NOT NULL
- ,default_max_wire_fee_val INT8 NOT NULL
- ,default_max_wire_fee_frac INT4 NOT NULL
- ,default_wire_fee_amortization INT4 NOT NULL
+ ,use_stefan BOOLEAN NOT NULL DEFAULT TRUE
,default_wire_transfer_delay INT8 NOT NULL
,default_pay_delay INT8 NOT NULL
+ ,user_type INT4
);
COMMENT ON TABLE merchant_instances
IS 'all the instances supported by this backend';
@@ -89,15 +99,50 @@ COMMENT ON COLUMN merchant_instances.merchant_id
COMMENT ON COLUMN merchant_instances.merchant_name
IS 'legal name of the merchant as a simple string (required)';
COMMENT ON COLUMN merchant_instances.address
- IS 'physical address of the merchant as a Location in JSON format (required)';
+ IS 'physical address of the merchant as a location in JSON format (required)';
COMMENT ON COLUMN merchant_instances.jurisdiction
- IS 'jurisdiction of the merchant as a Location in JSON format (required)';
+ IS 'jurisdiction of the merchant as a location in JSON format (required)';
+COMMENT ON COLUMN merchant_instances.website
+ IS 'merchant site URL';
+COMMENT ON COLUMN merchant_instances.use_stefan
+ IS 'use STEFAN curve of exchange to determine acceptable fees (unless given explicitly)';
+COMMENT ON COLUMN merchant_instances.email
+ IS 'email';
+COMMENT ON COLUMN merchant_instances.logo
+ IS 'data image url';
COMMENT ON COLUMN merchant_instances.auth_hash
- IS 'hash used for merchant back office Authorization, NULL for no check';
+ IS 'hash used for merchant back office authorization, NULL for no check';
COMMENT ON COLUMN merchant_instances.auth_salt
IS 'salt to use when hashing Authorization header before comparing with auth_hash';
+COMMENT ON COLUMN merchant_instances.user_type
+ IS 'what type of user is this (individual or business)';
+CREATE TABLE IF NOT EXISTS merchant_login_tokens
+ (token BYTEA NOT NULL UNIQUE CHECK (LENGTH(token)=32),
+ creation_time INT8 NOT NULL,
+ expiration_time INT8 NOT NULL,
+ validity_scope INT4 NOT NULL,
+ merchant_serial BIGINT
+ REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
+ );
+COMMENT ON TABLE merchant_login_tokens
+ IS 'login tokens that have been created for the given instance';
+COMMENT ON COLUMN merchant_login_tokens.token
+ IS 'binary value of the login token';
+COMMENT ON COLUMN merchant_login_tokens.creation_time
+ IS 'time when the token was created; currently not used, potentially useful in the future for a forced logout of all tokens issued before a certain date';
+COMMENT ON COLUMN merchant_login_tokens.expiration_time
+ IS 'determines when the token expires';
+COMMENT ON COLUMN merchant_login_tokens.validity_scope
+ IS 'identifies the operations for which the token is valid';
+COMMENT ON COLUMN merchant_login_tokens.merchant_serial
+ IS 'identifies the instance for which the token is valid';
+
+CREATE INDEX IF NOT EXISTS merchant_login_tokens_by_expiration
+ ON merchant_login_tokens
+ (expiration_time);
+
CREATE TABLE IF NOT EXISTS merchant_keys
(merchant_priv BYTEA NOT NULL UNIQUE CHECK (LENGTH(merchant_priv)=32),
@@ -113,7 +158,10 @@ CREATE TABLE IF NOT EXISTS merchant_accounts
REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
,h_wire BYTEA NOT NULL CHECK (LENGTH(h_wire)=64)
,salt BYTEA NOT NULL CHECK (LENGTH(salt)=16)
- ,payto_uri VARCHAR NOT NULL
+ ,credit_facade_url TEXT
+ ,credit_facade_credentials TEXT
+ ,last_bank_serial INT8 NOT NULL DEFAULT (0)
+ ,payto_uri TEXT NOT NULL
,active BOOLEAN NOT NULL
,UNIQUE (merchant_serial,payto_uri)
,UNIQUE (h_wire)
@@ -128,6 +176,12 @@ COMMENT ON COLUMN merchant_accounts.payto_uri
IS 'payto URI of a merchant bank account';
COMMENT ON COLUMN merchant_accounts.active
IS 'true if we actively use this bank account, false if it is just kept around for older contracts to refer to';
+COMMENT ON COLUMN merchant_accounts.credit_facade_url
+ IS 'Base URL of a facade where the merchant can inquire about incoming bank transactions into this account';
+COMMENT ON COLUMN merchant_accounts.credit_facade_credentials
+ IS 'JSON with credentials needed to access the credit facade';
+COMMENT ON COLUMN merchant_accounts.last_bank_serial
+ IS 'Serial number of the bank of the last transaction we successfully imported';
-------------------------- Inventory ---------------------------
@@ -136,14 +190,13 @@ CREATE TABLE IF NOT EXISTS merchant_inventory
(product_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,merchant_serial BIGINT NOT NULL
REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
- ,product_id VARCHAR NOT NULL
- ,description VARCHAR NOT NULL
+ ,product_id TEXT NOT NULL
+ ,description TEXT NOT NULL
,description_i18n BYTEA NOT NULL
- ,unit VARCHAR NOT NULL
+ ,unit TEXT NOT NULL
,image BYTEA NOT NULL
,taxes BYTEA NOT NULL
- ,price_val INT8 NOT NULL
- ,price_frac INT4 NOT NULL
+ ,price taler_amount_currency NOT NULL
,total_stock BIGINT NOT NULL
,total_sold BIGINT NOT NULL DEFAULT 0
,total_lost BIGINT NOT NULL DEFAULT 0
@@ -164,7 +217,7 @@ COMMENT ON COLUMN merchant_inventory.image
IS 'NOT NULL, but can be 0 bytes; must contain an ImageDataUrl';
COMMENT ON COLUMN merchant_inventory.taxes
IS 'JSON array containing taxes the merchant pays, must be JSON, but can be just "[]"';
-COMMENT ON COLUMN merchant_inventory.price_val
+COMMENT ON COLUMN merchant_inventory.price
IS 'Current price of one unit of the product';
COMMENT ON COLUMN merchant_inventory.total_stock
IS 'A value of -1 is used for unlimited (electronic good), may never be lowered';
@@ -207,12 +260,14 @@ CREATE TABLE IF NOT EXISTS merchant_orders
(order_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,merchant_serial BIGINT NOT NULL
REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
- ,order_id VARCHAR NOT NULL
+ ,order_id TEXT NOT NULL
,claim_token BYTEA NOT NULL CHECK (LENGTH(claim_token)=16)
,h_post_data BYTEA NOT NULL CHECK (LENGTH(h_post_data)=64)
,pay_deadline INT8 NOT NULL
,creation_time INT8 NOT NULL
,contract_terms BYTEA NOT NULL
+ ,pos_key TEXT DEFAULT NULL
+ ,pos_algorithm INT NOT NULL DEFAULT (0)
,UNIQUE (merchant_serial, order_id)
);
COMMENT ON TABLE merchant_orders
@@ -227,6 +282,12 @@ COMMENT ON COLUMN merchant_orders.merchant_serial
IS 'Identifies the instance offering the contract';
COMMENT ON COLUMN merchant_orders.pay_deadline
IS 'How long is the offer valid. After this time, the order can be garbage collected';
+COMMENT ON COLUMN merchant_orders.pos_key
+ IS 'encoded based key which is used for the verification of payment';
+COMMENT ON COLUMN merchant_orders.pos_algorithm
+ IS 'algorithm to used to generate the confirmation code. It is link with the pos_key';
+
+
CREATE INDEX IF NOT EXISTS merchant_orders_by_expiration
ON merchant_orders
(pay_deadline);
@@ -253,16 +314,19 @@ CREATE TABLE IF NOT EXISTS merchant_contract_terms
(order_serial BIGINT PRIMARY KEY
,merchant_serial BIGINT NOT NULL
REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
- ,order_id VARCHAR NOT NULL
+ ,order_id TEXT NOT NULL
,contract_terms BYTEA NOT NULL
+ ,wallet_data TEXT DEFAULT NULL
,h_contract_terms BYTEA NOT NULL CHECK (LENGTH(h_contract_terms)=64)
,creation_time INT8 NOT NULL
,pay_deadline INT8 NOT NULL
,refund_deadline INT8 NOT NULL
,paid BOOLEAN DEFAULT FALSE NOT NULL
,wired BOOLEAN DEFAULT FALSE NOT NULL
- ,fulfillment_url VARCHAR
- ,session_id VARCHAR DEFAULT '' NOT NULL
+ ,fulfillment_url TEXT
+ ,session_id TEXT DEFAULT '' NOT NULL
+ ,pos_key TEXT DEFAULT NULL
+ ,pos_algorithm INT NOT NULL DEFAULT (0)
,claim_token BYTEA NOT NULL CHECK (LENGTH(claim_token)=16)
,UNIQUE (merchant_serial, order_id)
,UNIQUE (merchant_serial, h_contract_terms)
@@ -275,8 +339,12 @@ COMMENT ON COLUMN merchant_contract_terms.merchant_serial
IS 'Identifies the instance offering the contract';
COMMENT ON COLUMN merchant_contract_terms.contract_terms
IS 'These contract terms include the wallet nonce';
+COMMENT ON COLUMN merchant_contract_terms.wallet_data
+ IS 'Data provided by the wallet when paying for the contract (subcontract selection, blinded tokens, etc.)';
COMMENT ON COLUMN merchant_contract_terms.h_contract_terms
IS 'Hash over contract_terms';
+COMMENT ON COLUMN merchant_contract_terms.pay_deadline
+ IS 'How long is the offer valid. After this time, the order can be garbage collected';
COMMENT ON COLUMN merchant_contract_terms.refund_deadline
IS 'By what times do refunds have to be approved (useful to reject refund requests)';
COMMENT ON COLUMN merchant_contract_terms.paid
@@ -289,6 +357,11 @@ COMMENT ON COLUMN merchant_contract_terms.session_id
IS 'last session_id from we confirmed the paying client to use, empty string for none';
COMMENT ON COLUMN merchant_contract_terms.pay_deadline
IS 'How long is the offer valid. After this time, the order can be garbage collected';
+COMMENT ON COLUMN merchant_contract_terms.pos_key
+ IS 'enconded based key which is used for the verification of payment';
+COMMENT ON COLUMN merchant_orders.pos_algorithm
+ IS 'algorithm to used to generate the confirmation code. It is link with the pos_key';
+
COMMENT ON COLUMN merchant_contract_terms.claim_token
IS 'Token optionally used to access the status of the order. All zeros (not NULL) if not used';
@@ -312,39 +385,61 @@ CREATE INDEX IF NOT EXISTS merchant_contract_terms_by_merchant_session_and_fulfi
---------------- Payment and refunds ---------------------------
-CREATE TABLE IF NOT EXISTS merchant_deposits
- (deposit_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+CREATE TABLE IF NOT EXISTS merchant_deposit_confirmations
+ (deposit_confirmation_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,order_serial BIGINT
REFERENCES merchant_contract_terms (order_serial) ON DELETE CASCADE
,deposit_timestamp INT8 NOT NULL
- ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
- ,exchange_url VARCHAR NOT NULL
- ,amount_with_fee_val INT8 NOT NULL
- ,amount_with_fee_frac INT4 NOT NULL
- ,deposit_fee_val INT8 NOT NULL
- ,deposit_fee_frac INT4 NOT NULL
- ,refund_fee_val INT8 NOT NULL
- ,refund_fee_frac INT4 NOT NULL
- ,wire_fee_val INT8 NOT NULL
- ,wire_fee_frac INT4 NOT NULL
+ ,exchange_url TEXT NOT NULL
+ ,total_without_fee taler_amount_currency NOT NULL
+ ,wire_fee taler_amount_currency NOT NULL
,signkey_serial BIGINT NOT NULL
REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE CASCADE
,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64)
,account_serial BIGINT NOT NULL
REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
- ,UNIQUE (order_serial, coin_pub)
+ ,UNIQUE (order_serial, exchange_sig)
);
-COMMENT ON TABLE merchant_deposits
+COMMENT ON TABLE merchant_deposit_confirmations
IS 'Table with the deposit confirmations for each coin we deposited at the exchange';
-COMMENT ON COLUMN merchant_deposits.signkey_serial
+COMMENT ON COLUMN merchant_deposit_confirmations.signkey_serial
IS 'Online signing key of the exchange on the deposit confirmation';
-COMMENT ON COLUMN merchant_deposits.deposit_timestamp
+COMMENT ON COLUMN merchant_deposit_confirmations.deposit_timestamp
IS 'Time when the exchange generated the deposit confirmation';
-COMMENT ON COLUMN merchant_deposits.exchange_sig
+COMMENT ON COLUMN merchant_deposit_confirmations.exchange_sig
IS 'Signature of the exchange over the deposit confirmation';
-COMMENT ON COLUMN merchant_deposits.wire_fee_val
+COMMENT ON COLUMN merchant_deposit_confirmations.wire_fee
IS 'We MAY want to see if we should try to get this via merchant_exchange_wire_fees (not sure, may be too complicated with the date range, etc.)';
+
+CREATE TABLE IF NOT EXISTS merchant_deposits
+ (deposit_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ ,coin_offset INT4 NOT NULL
+ ,deposit_confirmation_serial BIGINT NOT NULL
+ REFERENCES merchant_deposit_confirmations (deposit_confirmation_serial) ON DELETE CASCADE
+ ,coin_pub BYTEA NOT NULL CHECK (LENGTH(coin_pub)=32)
+ ,coin_sig BYTEA NOT NULL CHECK (LENGTH(coin_sig)=64)
+ ,amount_with_fee taler_amount_currency NOT NULL
+ ,deposit_fee taler_amount_currency NOT NULL
+ ,refund_fee taler_amount_currency NOT NULL
+ ,UNIQUE (deposit_confirmation_serial, coin_pub)
+ );
+COMMENT ON TABLE merchant_deposits
+ IS 'Table with the deposit details for each coin we deposited at the exchange';
+COMMENT ON COLUMN merchant_deposits.coin_offset
+ IS 'Offset of this coin in the batch';
+COMMENT ON COLUMN merchant_deposits.deposit_confirmation_serial
+ IS 'Reference to the deposit confirmation of the exchange';
+COMMENT ON COLUMN merchant_deposits.coin_pub
+ IS 'Public key of the coin that was deposited';
+COMMENT ON COLUMN merchant_deposits.amount_with_fee
+ IS 'Total amount (incl. fee) of the coin that was deposited';
+COMMENT ON COLUMN merchant_deposits.deposit_fee
+ IS 'Deposit fee (for this coin) that was paid';
+COMMENT ON COLUMN merchant_deposits.refund_fee
+ IS 'How high would the refund fee be (for this coin)';
+
+
CREATE TABLE IF NOT EXISTS merchant_refunds
(refund_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,order_serial BIGINT NOT NULL
@@ -352,9 +447,8 @@ CREATE TABLE IF NOT EXISTS merchant_refunds
,rtransaction_id BIGINT NOT NULL
,refund_timestamp INT8 NOT NULL
,coin_pub BYTEA NOT NULL
- ,reason VARCHAR NOT NULL
- ,refund_amount_val INT8 NOT NULL
- ,refund_amount_frac INT4 NOT NULL
+ ,reason TEXT NOT NULL
+ ,refund_amount taler_amount_currency NOT NULL
,UNIQUE (order_serial, coin_pub, rtransaction_id)
);
COMMENT ON TABLE merchant_deposits
@@ -380,13 +474,15 @@ COMMENT ON TABLE merchant_refund_proofs
-------------------- Wire transfers ---------------------------
CREATE TABLE IF NOT EXISTS merchant_transfers
- (credit_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
- ,exchange_url VARCHAR NOT NULL
+ (credit_serial INT8 GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ ,exchange_url TEXT NOT NULL
,wtid BYTEA CHECK (LENGTH(wtid)=32)
- ,credit_amount_val INT8 NOT NULL
- ,credit_amount_frac INT4 NOT NULL
- ,account_serial BIGINT NOT NULL
- REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
+ ,credit_amount taler_amount_currency NOT NULL
+ ,account_serial INT8 NOT NULL
+ REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
+ ,ready_time INT8 NOT NULL DEFAULT (0)
+ ,validation_status INT4 DEFAULT NULL
+ ,failed BOOLEAN NOT NULL DEFAULT FALSE
,verified BOOLEAN NOT NULL DEFAULT FALSE
,confirmed BOOLEAN NOT NULL DEFAULT FALSE
,UNIQUE (wtid, exchange_url, account_serial)
@@ -397,18 +493,28 @@ COMMENT ON COLUMN merchant_transfers.verified
IS 'true once we got an acceptable response from the exchange for this transfer';
COMMENT ON COLUMN merchant_transfers.confirmed
IS 'true once the merchant confirmed that this transfer was received';
-COMMENT ON COLUMN merchant_transfers.credit_amount_val
+COMMENT ON COLUMN merchant_transfers.credit_amount
IS 'actual value of the (aggregated) wire transfer, excluding the wire fee, according to the merchant';
+COMMENT ON COLUMN merchant_transfers.failed
+ IS 'set to true on permanent verification failures';
+COMMENT ON COLUMN merchant_transfers.validation_status
+ IS 'Taler error code describing the state of the validation';
+
+CREATE INDEX merchant_transfers_by_open
+ ON merchant_transfers
+ (ready_time ASC)
+ WHERE confirmed AND NOT (failed OR verified);
+COMMENT ON INDEX merchant_transfers_by_open
+ IS 'For select_open_transfers';
+
CREATE TABLE IF NOT EXISTS merchant_transfer_signatures
(credit_serial BIGINT PRIMARY KEY
REFERENCES merchant_transfers (credit_serial) ON DELETE CASCADE
,signkey_serial BIGINT NOT NULL
REFERENCES merchant_exchange_signing_keys (signkey_serial) ON DELETE CASCADE
- ,wire_fee_val INT8 NOT NULL
- ,wire_fee_frac INT4 NOT NULL
- ,credit_amount_val INT8 NOT NULL
- ,credit_amount_frac INT4 NOT NULL
+ ,wire_fee taler_amount_currency NOT NULL
+ ,credit_amount taler_amount_currency NOT NULL
,execution_time INT8 NOT NULL
,exchange_sig BYTEA NOT NULL CHECK (LENGTH(exchange_sig)=64)
);
@@ -416,7 +522,7 @@ COMMENT ON TABLE merchant_transfer_signatures
IS 'table represents the main information returned from the /transfer request to the exchange.';
COMMENT ON COLUMN merchant_transfer_signatures.execution_time
IS 'Execution time as claimed by the exchange, roughly matches time seen by merchant';
-COMMENT ON COLUMN merchant_transfer_signatures.credit_amount_val
+COMMENT ON COLUMN merchant_transfer_signatures.credit_amount
IS 'actual value of the (aggregated) wire transfer, excluding the wire fee, according to the exchange';
@@ -426,26 +532,23 @@ CREATE TABLE IF NOT EXISTS merchant_transfer_to_coin
,credit_serial BIGINT NOT NULL
REFERENCES merchant_transfers (credit_serial) ON DELETE CASCADE
,offset_in_exchange_list INT8 NOT NULL
- ,exchange_deposit_value_val INT8 NOT NULL
- ,exchange_deposit_value_frac INT4 NOT NULL
- ,exchange_deposit_fee_val INT8 NOT NULL
- ,exchange_deposit_fee_frac INT4 NOT NULL
+ ,exchange_deposit_value taler_amount_currency NOT NULL
+ ,exchange_deposit_fee taler_amount_currency NOT NULL
);
CREATE INDEX IF NOT EXISTS merchant_transfers_by_credit
ON merchant_transfer_to_coin
(credit_serial);
COMMENT ON TABLE merchant_transfer_to_coin
IS 'Mapping of (credit) transfers to (deposited) coins';
-COMMENT ON COLUMN merchant_transfer_to_coin.exchange_deposit_value_val
+COMMENT ON COLUMN merchant_transfer_to_coin.exchange_deposit_value
IS 'Deposit value as claimed by the exchange, should match our values in merchant_deposits minus refunds';
-COMMENT ON COLUMN merchant_transfer_to_coin.exchange_deposit_fee_val
+COMMENT ON COLUMN merchant_transfer_to_coin.exchange_deposit_fee
IS 'Deposit value as claimed by the exchange, should match our values in merchant_deposits';
CREATE TABLE IF NOT EXISTS merchant_deposit_to_transfer
(deposit_serial BIGINT NOT NULL
REFERENCES merchant_deposits (deposit_serial) ON DELETE CASCADE
- ,coin_contribution_value_val INT8 NOT NULL
- ,coin_contribution_value_frac INT4 NOT NULL
+ ,coin_contribution_value taler_amount_currency NOT NULL
,credit_serial BIGINT NOT NULL
REFERENCES merchant_transfers (credit_serial)
,execution_time INT8 NOT NULL
@@ -460,111 +563,105 @@ COMMENT ON COLUMN merchant_deposit_to_transfer.execution_time
IS 'Execution time as claimed by the exchange, roughly matches time seen by merchant';
--------------------------- Tipping ---------------------------
+-------------------------- Rewards ---------------------------
-CREATE TABLE IF NOT EXISTS merchant_tip_reserves
+CREATE TABLE IF NOT EXISTS merchant_reward_reserves
(reserve_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,reserve_pub BYTEA NOT NULL UNIQUE CHECK (LENGTH(reserve_pub)=32)
,merchant_serial BIGINT NOT NULL
REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
,creation_time INT8 NOT NULL
,expiration INT8 NOT NULL
- ,merchant_initial_balance_val INT8 NOT NULL
- ,merchant_initial_balance_frac INT4 NOT NULL
- ,exchange_initial_balance_val INT8 NOT NULL DEFAULT 0
- ,exchange_initial_balance_frac INT4 NOT NULL DEFAULT 0
- ,tips_committed_val INT8 NOT NULL DEFAULT 0
- ,tips_committed_frac INT4 NOT NULL DEFAULT 0
- ,tips_picked_up_val INT8 NOT NULL DEFAULT 0
- ,tips_picked_up_frac INT4 NOT NULL DEFAULT 0
+ ,merchant_initial_balance taler_amount_currency NOT NULL
+ ,exchange_initial_balance taler_amount_currency NOT NULL
+ ,rewards_committed taler_amount_currency NOT NULL
+ ,rewards_picked_up taler_amount_currency NOT NULL
);
-COMMENT ON TABLE merchant_tip_reserves
- IS 'balances of the reserves available for tips';
-COMMENT ON COLUMN merchant_tip_reserves.expiration
+COMMENT ON TABLE merchant_reward_reserves
+ IS 'balances of the reserves available for rewards';
+COMMENT ON COLUMN merchant_reward_reserves.expiration
IS 'FIXME: EXCHANGE API needs to tell us when reserves close if we are to compute this';
-COMMENT ON COLUMN merchant_tip_reserves.merchant_initial_balance_val
+COMMENT ON COLUMN merchant_reward_reserves.merchant_initial_balance
IS 'Set to the initial balance the merchant told us when creating the reserve';
-COMMENT ON COLUMN merchant_tip_reserves.exchange_initial_balance_val
+COMMENT ON COLUMN merchant_reward_reserves.exchange_initial_balance
IS 'Set to the initial balance the exchange told us when we queried the reserve status';
-COMMENT ON COLUMN merchant_tip_reserves.tips_committed_val
- IS 'Amount of outstanding approved tips that have not been picked up';
-COMMENT ON COLUMN merchant_tip_reserves.tips_picked_up_val
- IS 'Total amount tips that have been picked up from this reserve';
-CREATE INDEX IF NOT EXISTS merchant_tip_reserves_by_reserve_pub_and_merchant_serial
- ON merchant_tip_reserves
+COMMENT ON COLUMN merchant_reward_reserves.rewards_committed
+ IS 'Amount of outstanding approved rewards that have not been picked up';
+COMMENT ON COLUMN merchant_reward_reserves.rewards_picked_up
+ IS 'Total amount rewards that have been picked up from this reserve';
+
+CREATE INDEX IF NOT EXISTS merchant_reward_reserves_by_reserve_pub_and_merchant_serial
+ ON merchant_reward_reserves
(reserve_pub,merchant_serial,creation_time);
-CREATE INDEX IF NOT EXISTS merchant_tip_reserves_by_merchant_serial_and_creation_time
- ON merchant_tip_reserves
+CREATE INDEX IF NOT EXISTS merchant_reward_reserves_by_merchant_serial_and_creation_time
+ ON merchant_reward_reserves
(merchant_serial,creation_time);
-CREATE INDEX IF NOT EXISTS merchant_tip_reserves_by_exchange_balance
- ON merchant_tip_reserves
- (exchange_initial_balance_val,exchange_initial_balance_frac);
+CREATE INDEX IF NOT EXISTS merchant_reward_reserves_by_exchange_balance
+ ON merchant_reward_reserves
+ (exchange_initial_balance);
-CREATE TABLE IF NOT EXISTS merchant_tip_reserve_keys
+CREATE TABLE IF NOT EXISTS merchant_reward_reserve_keys
(reserve_serial BIGINT NOT NULL UNIQUE
- REFERENCES merchant_tip_reserves (reserve_serial) ON DELETE CASCADE
+ REFERENCES merchant_reward_reserves (reserve_serial) ON DELETE CASCADE
,reserve_priv BYTEA NOT NULL UNIQUE CHECK (LENGTH(reserve_priv)=32)
- ,exchange_url VARCHAR NOT NULL
- ,payto_uri VARCHAR
+ ,exchange_url TEXT NOT NULL
+ ,master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)
);
-COMMENT ON TABLE merchant_tip_reserves
+COMMENT ON TABLE merchant_reward_reserves
IS 'private keys of reserves that have not been deleted';
-COMMENT ON COLUMN merchant_tip_reserve_keys.payto_uri
- IS 'payto:// URI used to fund the reserve, may be NULL once reserve is funded';
+COMMENT ON COLUMN merchant_reward_reserve_keys.master_pub
+ IS 'Master public key of the exchange to which the reserve belongs';
-CREATE TABLE IF NOT EXISTS merchant_tips
- (tip_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+CREATE TABLE IF NOT EXISTS merchant_rewards
+ (reward_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
,reserve_serial BIGINT NOT NULL
- REFERENCES merchant_tip_reserves (reserve_serial) ON DELETE CASCADE
- ,tip_id BYTEA NOT NULL UNIQUE CHECK (LENGTH(tip_id)=64)
- ,justification VARCHAR NOT NULL
- ,next_url VARCHAR NOT NULL
+ REFERENCES merchant_reward_reserves (reserve_serial) ON DELETE CASCADE
+ ,reward_id BYTEA NOT NULL UNIQUE CHECK (LENGTH(reward_id)=64)
+ ,justification TEXT NOT NULL
+ ,next_url TEXT NOT NULL
,expiration INT8 NOT NULL
- ,amount_val INT8 NOT NULL
- ,amount_frac INT4 NOT NULL
- ,picked_up_val INT8 NOT NULL DEFAULT 0
- ,picked_up_frac INT4 NOT NULL DEFAULT 0
+ ,amount taler_amount_currency NOT NULL
+ ,picked_up taler_amount_currency NOT NULL
,was_picked_up BOOLEAN NOT NULL DEFAULT FALSE
);
-CREATE INDEX IF NOT EXISTS merchant_tips_by_pickup_and_expiration
- ON merchant_tips
+CREATE INDEX IF NOT EXISTS merchant_rewards_by_pickup_and_expiration
+ ON merchant_rewards
(was_picked_up,expiration);
-COMMENT ON TABLE merchant_tips
- IS 'tips that have been authorized';
-COMMENT ON COLUMN merchant_tips.amount_val
- IS 'Overall tip amount';
-COMMENT ON COLUMN merchant_tips.picked_up_val
- IS 'Tip amount left to be picked up';
-COMMENT ON COLUMN merchant_tips.reserve_serial
- IS 'Reserve from which this tip is funded';
-COMMENT ON COLUMN merchant_tips.expiration
- IS 'by when does the client have to pick up the tip';
-
-CREATE TABLE IF NOT EXISTS merchant_tip_pickups
+COMMENT ON TABLE merchant_rewards
+ IS 'rewards that have been authorized';
+COMMENT ON COLUMN merchant_rewards.amount
+ IS 'Overall reward amount';
+COMMENT ON COLUMN merchant_rewards.picked_up
+ IS 'Reward amount left to be picked up';
+COMMENT ON COLUMN merchant_rewards.reserve_serial
+ IS 'Reserve from which this reward is funded';
+COMMENT ON COLUMN merchant_rewards.expiration
+ IS 'by when does the client have to pick up the reward';
+
+CREATE TABLE IF NOT EXISTS merchant_reward_pickups
(pickup_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY NOT NULL
- ,tip_serial BIGINT NOT NULL
- REFERENCES merchant_tips (tip_serial) ON DELETE CASCADE
+ ,reward_serial BIGINT NOT NULL
+ REFERENCES merchant_rewards (reward_serial) ON DELETE CASCADE
,pickup_id BYTEA NOT NULL UNIQUE CHECK (LENGTH(pickup_id)=64)
- ,amount_val INT8 NOT NULL
- ,amount_frac INT4 NOT NULL
+ ,amount taler_amount_currency NOT NULL
);
-COMMENT ON TABLE merchant_tip_pickups
- IS 'tips that have been picked up';
-COMMENT ON COLUMN merchant_tips.amount_val
+COMMENT ON TABLE merchant_reward_pickups
+ IS 'rewards that have been picked up';
+COMMENT ON COLUMN merchant_rewards.amount
IS 'total transaction cost for all coins including withdraw fees';
-CREATE TABLE IF NOT EXISTS merchant_tip_pickup_signatures
+CREATE TABLE IF NOT EXISTS merchant_reward_pickup_signatures
(pickup_serial INT8 NOT NULL
- REFERENCES merchant_tip_pickups (pickup_serial) ON DELETE CASCADE
+ REFERENCES merchant_reward_pickups (pickup_serial) ON DELETE CASCADE
,coin_offset INT4 NOT NULL
,blind_sig BYTEA NOT NULL
,PRIMARY KEY (pickup_serial, coin_offset)
);
-COMMENT ON TABLE merchant_tip_pickup_signatures
- IS 'blind signatures we got from the exchange during the tip pickup';
+COMMENT ON TABLE merchant_reward_pickup_signatures
+ IS 'blind signatures we got from the exchange during the reward pickup';
@@ -573,12 +670,13 @@ CREATE TABLE IF NOT EXISTS merchant_kyc
(kyc_serial_id BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
,kyc_timestamp INT8 NOT NULL
,kyc_ok BOOLEAN NOT NULL DEFAULT (FALSE)
+,aml_decision INT4 NOT NULL DEFAULT (0)
,exchange_sig BYTEA CHECK(LENGTH(exchange_sig)=64)
,exchange_pub BYTEA CHECK(LENGTH(exchange_pub)=32)
,exchange_kyc_serial INT8 NOT NULL DEFAULT(0)
,account_serial INT8 NOT NULL
REFERENCES merchant_accounts (account_serial) ON DELETE CASCADE
-,exchange_url VARCHAR NOT NULL
+,exchange_url TEXT NOT NULL
,PRIMARY KEY (account_serial,exchange_url)
);
COMMENT ON TABLE merchant_kyc
@@ -593,11 +691,153 @@ COMMENT ON COLUMN merchant_kyc.exchange_sig
IS 'signature of the exchange affirming the KYC passed (or NULL if exchange does not require KYC or not kyc_ok)';
COMMENT ON COLUMN merchant_kyc.exchange_pub
IS 'public key used with exchange_sig (or NULL if exchange_sig is NULL)';
+COMMENT ON COLUMN merchant_kyc.aml_decision
+ IS 'current AML decision for our account at the exchange';
COMMENT ON COLUMN merchant_kyc.account_serial
IS 'Which bank account of the merchant is the KYC status for';
COMMENT ON COLUMN merchant_kyc.exchange_url
IS 'Which exchange base URL is this KYC status valid for';
+CREATE TABLE IF NOT EXISTS merchant_otp_devices
+ (otp_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ ,merchant_serial BIGINT NOT NULL
+ REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
+ ,otp_id TEXT NOT NULL
+ ,otp_description TEXT NOT NULL
+ ,otp_key TEXT DEFAULT NULL
+ ,otp_algorithm INT NOT NULL DEFAULT (0)
+ ,otp_ctr INT8 NOT NULL DEFAULT (0)
+ ,UNIQUE (merchant_serial, otp_id)
+ );
+COMMENT ON TABLE merchant_otp_devices
+ IS 'OTP device owned by a merchant';
+COMMENT ON COLUMN merchant_otp_devices.otp_description
+ IS 'Human-readable OTP device description';
+COMMENT ON COLUMN merchant_otp_devices.otp_key
+ IS 'A base64-encoded key of the point-of-sale. It will be use by the OTP device';
+COMMENT ON COLUMN merchant_otp_devices.otp_algorithm
+ IS 'algorithm to used to generate the confirmation code. It is linked with the otp_key and otp_ctr';
+COMMENT ON COLUMN merchant_otp_devices.otp_ctr
+ IS 'counter for counter-based OTP generators';
+
+
+CREATE TABLE IF NOT EXISTS merchant_template
+ (template_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ ,merchant_serial BIGINT NOT NULL
+ REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
+ ,template_id TEXT NOT NULL
+ ,template_description TEXT NOT NULL
+ ,otp_device_id BIGINT
+ REFERENCES merchant_otp_devices (otp_serial) ON DELETE SET NULL
+ ,template_contract TEXT NOT NULL -- in JSON format
+ ,UNIQUE (merchant_serial, template_id)
+ );
+COMMENT ON TABLE merchant_template
+ IS 'template used by the merchant (may be incomplete, frontend can override)';
+COMMENT ON COLUMN merchant_template.template_description
+ IS 'Human-readable template description';
+COMMENT ON COLUMN merchant_template.template_contract
+ IS 'The template contract will contains some additional information.';
+
+
+
+CREATE TABLE IF NOT EXISTS merchant_webhook
+ (webhook_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ ,merchant_serial BIGINT NOT NULL
+ REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
+ ,webhook_id TEXT NOT NULL
+ ,event_type TEXT NOT NULL
+ ,url TEXT NOT NULL
+ ,http_method TEXT NOT NULL
+ ,header_template TEXT
+ ,body_template TEXT
+ ,UNIQUE (merchant_serial, webhook_id)
+ );
+COMMENT ON TABLE merchant_webhook
+ IS 'webhook used by the merchant (may be incomplete, frontend can override)';
+COMMENT ON COLUMN merchant_webhook.event_type
+ IS 'Event of the webhook';
+COMMENT ON COLUMN merchant_webhook.url
+ IS 'URL to make the request to';
+COMMENT ON COLUMN merchant_webhook.http_method
+ IS 'http method use by the merchant';
+COMMENT ON COLUMN merchant_webhook.header_template
+ IS 'Template for the header of the webhook, to be modified based on trigger data';
+COMMENT ON COLUMN merchant_webhook.body_template
+ IS 'Template for the body of the webhook, to be modified based on trigger data';
+
+
+CREATE TABLE IF NOT EXISTS merchant_pending_webhooks
+ (webhook_pending_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ ,merchant_serial BIGINT NOT NULL
+ REFERENCES merchant_instances (merchant_serial) ON DELETE CASCADE
+ ,webhook_serial BIGINT NOT NULL
+ REFERENCES merchant_webhook (webhook_serial) ON DELETE CASCADE
+ ,next_attempt INT8 NOT NULL DEFAULT(0)
+ ,retries INT4 NOT NULL DEFAULT(0)
+ ,url TEXT NOT NULL
+ ,http_method TEXT NOT NULL
+ ,header TEXT
+ ,body TEXT
+ ,UNIQUE (merchant_serial, webhook_pending_serial)
+ );
+COMMENT ON TABLE merchant_pending_webhooks
+ IS 'webhooks that still need to be executed by the merchant';
+COMMENT ON COLUMN merchant_pending_webhooks.url
+ IS 'URL to make the request to';
+COMMENT ON COLUMN merchant_pending_webhooks.webhook_serial
+ IS 'Reference to the configured webhook template';
+COMMENT ON COLUMN merchant_pending_webhooks.retries
+ IS 'How often have we tried this request so far';
+COMMENT ON COLUMN merchant_pending_webhooks.next_attempt
+ IS 'Time when we should make the next request to the webhook';
+COMMENT ON COLUMN merchant_pending_webhooks.http_method
+ IS 'http method use for the webhook';
+COMMENT ON COLUMN merchant_pending_webhooks.header
+ IS 'Header of the webhook';
+COMMENT ON COLUMN merchant_pending_webhooks.body
+ IS 'Body of the webhook';
+
+
+CREATE TABLE IF NOT EXISTS merchant_exchange_accounts
+ (mea_serial BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
+ ,master_pub BYTEA NOT NULL CHECK (LENGTH(master_pub)=32)
+ ,payto_uri TEXT NOT NULL
+ ,conversion_url TEXT
+ ,debit_restrictions TEXT NOT NULL
+ ,credit_restrictions TEXT NOT NULL
+ ,master_sig BYTEA NOT NULL CHECK (LENGTH(master_sig)=64)
+ );
+COMMENT ON TABLE merchant_exchange_accounts
+ IS 'Here we store which bank accounts the exchange uses and with which constraints';
+COMMENT ON COLUMN merchant_exchange_accounts.master_pub
+ IS 'Master public key of the exchange with these accounts';
+COMMENT ON COLUMN merchant_exchange_accounts.payto_uri
+ IS 'RFC 8905 URI of the exchange bank account';
+COMMENT ON COLUMN merchant_exchange_accounts.conversion_url
+ IS 'NULL if this account does not require currency conversion';
+COMMENT ON COLUMN merchant_exchange_accounts.debit_restrictions
+ IS 'JSON array with account restrictions';
+COMMENT ON COLUMN merchant_exchange_accounts.credit_restrictions
+ IS 'JSON array with account restrictions';
+
+
+CREATE TABLE IF NOT EXISTS merchant_exchange_keys
+ (mek_serial BIGINT GENERATED BY DEFAULT AS IDENTITY UNIQUE
+ ,exchange_url TEXT PRIMARY KEY
+ ,keys_json TEXT NOT NULL
+ ,expiration_time INT8 NOT NULL
+ );
+COMMENT ON TABLE merchant_exchange_keys
+ IS 'Here we store the cached /keys response from an exchange in JSON format';
+COMMENT ON COLUMN merchant_exchange_keys.exchange_url
+ IS 'Base URL of the exchange with these keys';
+COMMENT ON COLUMN merchant_exchange_keys.keys_json
+ IS 'JSON string of the /keys as generated by libtalerexchange';
+COMMENT ON COLUMN merchant_exchange_keys.expiration_time
+ IS 'When should this /keys object be deleted';
+
+
-- Complete transaction
COMMIT;