Skip to content
This repository was archived by the owner on Jun 17, 2025. It is now read-only.

Commit ca4770a

Browse files
author
cmd
committed
update
1 parent d23c58f commit ca4770a

File tree

20 files changed

+385
-310
lines changed

20 files changed

+385
-310
lines changed

src/client/api/contract.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function list_contract_api (client : EscrowClient) {
7474
token : string
7575
) : Promise<ApiResponse<ContractListResponse>> => {
7676
// Formulate the request.
77-
const url = `${client.host}/api/contract/list?pubkey=${pubkey}`
77+
const url = `${client.host}/api/contract/list/${pubkey}`
7878
// Return the response.
7979
return client.fetcher<ContractListResponse>({ url, token })
8080
}

src/client/api/deposit.ts

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,38 @@
11

22
import { EscrowClient } from '../class/client.js'
3-
import { validate_registration } from '@/validators/index.js'
3+
import { validate_register_req } from '@/validators/index.js'
44

55
import {
66
CovenantData,
77
ReturnData,
88
ApiResponse,
9-
DepositRequest,
9+
AccountRequest,
1010
AccountDataResponse,
1111
DepositDataResponse,
1212
DepositListResponse,
13-
FundingDataResponse
13+
FundingDataResponse,
14+
RegisterRequest
1415
} from '@/types/index.js'
1516

1617
import * as assert from '@/assert.js'
1718

1819
/**
1920
* Request a deposit account from the provider.
2021
*/
21-
function request_deposit_api (client : EscrowClient) {
22+
function request_account_api (client : EscrowClient) {
2223
return async (
23-
req : DepositRequest
24+
request : AccountRequest
2425
) : Promise<ApiResponse<AccountDataResponse>> => {
25-
// Ensure params are string values.
26-
const arr = Object.entries(req)
27-
// Build a query string with params.
28-
const qry = new URLSearchParams(arr).toString()
2926
// Formulate the request.
30-
const url = `${client.host}/api/deposit/request?${qry}`
27+
const url = `${client.host}/api/deposit/request`
28+
// Formulate the request.
29+
const init = {
30+
method : 'POST',
31+
body : JSON.stringify(request),
32+
headers : { 'content-type' : 'application/json' }
33+
}
3134
// Return the response.
32-
return client.fetcher<AccountDataResponse>({ url })
35+
return client.fetcher<AccountDataResponse>({ url, init })
3336
}
3437
}
3538

@@ -38,19 +41,16 @@ function request_deposit_api (client : EscrowClient) {
3841
*/
3942
function register_deposit_api (client : EscrowClient) {
4043
return async (
41-
agent_id : string,
42-
return_tx : string
44+
request : RegisterRequest
4345
) : Promise<ApiResponse<DepositDataResponse>> => {
44-
// Create template
45-
const tmpl = { agent_id, return_tx }
46-
// Validate the deposit template.
47-
validate_registration({ agent_id, return_tx })
46+
// Validate the request.
47+
validate_register_req(request)
4848
// Configure the url.
4949
const url = `${client.host}/api/deposit/register`
5050
// Formulate the request.
5151
const init = {
5252
method : 'POST',
53-
body : JSON.stringify(tmpl),
53+
body : JSON.stringify(request),
5454
headers : { 'content-type' : 'application/json' }
5555
}
5656
// Return the response.
@@ -63,22 +63,18 @@ function register_deposit_api (client : EscrowClient) {
6363
*/
6464
function register_funds_api (client : EscrowClient) {
6565
return async (
66-
agent_id : string,
67-
return_tx : string,
68-
covenant : CovenantData
66+
request : RegisterRequest
6967
) : Promise<ApiResponse<FundingDataResponse>> => {
7068
// Assert that a covenant is defined.
71-
assert.ok(covenant !== undefined, 'covenant is undefined')
72-
// Create a deposit template.
73-
const templ = { agent_id, return_tx, covenant }
74-
// Validate the deposit template.
75-
validate_registration(templ)
69+
assert.ok(request.covenant !== undefined, 'covenant is undefined')
70+
// Validate the request.
71+
validate_register_req(request)
7672
// Formulate the request url.
7773
const url = `${client.host}/api/deposit/register`
7874
// Forulate the request body.
7975
const init = {
80-
method : 'POST',
81-
body : JSON.stringify(templ),
76+
method : 'POST',
77+
body : JSON.stringify(request),
8278
headers : { 'content-type' : 'application/json' }
8379
}
8480
// Return the response.
@@ -108,7 +104,7 @@ function list_deposit_api (client : EscrowClient) {
108104
token : string
109105
) : Promise<ApiResponse<DepositListResponse>> => {
110106
// Formulate the request.
111-
const url = `${client.host}/api/deposit/list?pubkey=${pubkey}`
107+
const url = `${client.host}/api/deposit/list/${pubkey}`
112108
// Return the response.
113109
return client.fetcher<DepositListResponse>({ url, token })
114110
}
@@ -153,7 +149,7 @@ export default function (client : EscrowClient) {
153149
commit : commit_funds_api(client),
154150
fund : register_funds_api(client),
155151
register : register_deposit_api(client),
156-
request : request_deposit_api(client),
152+
request : request_account_api(client),
157153
close : close_deposit_api(client)
158154
}
159155
}

src/client/api/depositor.ts

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Buff } from '@cmdcode/buff'
2-
import { create_return_tx } from '@/lib/return.js'
2+
import { parse_extkey } from '@cmdcode/crypto-tools/hd'
33
import { EscrowSigner } from '@/client/class/signer.js'
44
import { get_deposit_ctx } from '@/lib/deposit.js'
5-
import { verify_account } from '@/validators/deposit.js'
5+
import { verify_account } from '@/client/validators/deposit.js'
66

77
import {
88
create_covenant,
9-
create_return
9+
create_return_psig
1010
} from '@/lib/session.js'
1111

1212
import {
@@ -16,113 +16,102 @@ import {
1616
CovenantData,
1717
DepositAccount,
1818
DepositData,
19-
ReturnData,
2019
TxOutput
2120
} from '@/types/index.js'
2221

23-
export function request_account_api (client : EscrowSigner) {
22+
export function request_account_api (signer : EscrowSigner) {
2423
return async (
25-
locktime : number
24+
locktime : number,
25+
index ?: number
2626
) : Promise<ApiResponse<AccountDataResponse>> => {
27-
const pubkey = client.pubkey
28-
return client.client.deposit.request({ pubkey, locktime })
27+
const deposit_pk = signer.pubkey
28+
const spend_xpub = signer.get_account(index).xpub
29+
const req = { deposit_pk, locktime, spend_xpub }
30+
return signer.client.deposit.request(req)
2931
}
3032
}
3133

3234
export function verify_account_api (signer : EscrowSigner) {
3335
return (account : DepositAccount) : void => {
34-
const host_pub = signer.host_pub
35-
const network = signer.client.network
36-
if (host_pub === undefined) {
37-
throw new Error('host pubkey is not set on device')
38-
}
39-
verify_account(account, signer.pubkey, host_pub, network)
40-
}
41-
}
42-
43-
/**
44-
* Create a deposit template for registration.
45-
*/
46-
export function register_utxo_api (client : EscrowSigner) {
47-
return async (
48-
account : DepositAccount,
49-
utxo : TxOutput,
50-
txfee ?: number
51-
) : Promise<string> => {
52-
// Unpack the deposit object.
53-
const { agent_pk, sequence } = account
54-
// Define our pubkey.
55-
const pub = client.pubkey
56-
const idx = Buff.hex(utxo.txid).slice(0, 4).num
57-
const addr = client._wallet.get_account(idx).new_address()
58-
// Get the context object for our deposit account.
59-
const ctx = get_deposit_ctx(agent_pk, pub, sequence)
60-
// Create the return transaction.
61-
return create_return_tx(addr, ctx, client._signer, utxo, txfee)
36+
verify_account(account, signer)
6237
}
6338
}
6439

65-
export function commit_utxo_api (client : EscrowSigner) {
40+
export function commit_utxo_api (signer : EscrowSigner) {
6641
return async (
6742
account : DepositAccount,
6843
contract : ContractData,
6944
utxo : TxOutput
7045
) : Promise<CovenantData> => {
7146
// Unpack the deposit object.
72-
const { agent_pk, sequence } = account
73-
// Define our pubkey.
74-
const pub = client.pubkey
47+
const { agent_pk, sequence, spend_xpub } = account
48+
// Check if account xpub is valid.
49+
if (!signer.has_account(spend_xpub)) {
50+
throw new Error('account xpub is not recognized by master wallet')
51+
}
52+
// Define our pubkey as the deposit pubkey.
53+
const deposit_pk = signer.pubkey
54+
// Define our xpub as the return pubkey.
55+
const return_pk = parse_extkey(spend_xpub).pubkey
7556
// Get the context object for our deposit account.
76-
const ctx = get_deposit_ctx(agent_pk, pub, sequence)
57+
const ctx = get_deposit_ctx(agent_pk, deposit_pk, return_pk, sequence)
7758
// Create a covenant with the contract and deposit.
78-
return create_covenant(ctx, contract, client._signer, utxo)
59+
return create_covenant(ctx, contract, signer._signer, utxo)
7960
}
8061
}
8162

82-
export function commit_deposit_api (client : EscrowSigner) {
63+
export function commit_deposit_api (signer : EscrowSigner) {
8364
return async (
8465
contract : ContractData,
8566
deposit : DepositData
8667
) : Promise<CovenantData> => {
8768
// Unpack the deposit object.
88-
const { agent_pk, sequence, txid, vout, value, scriptkey } = deposit
89-
// Define our pubkey.
90-
const pub = client.pubkey
69+
const {
70+
agent_pk, sequence, txid, vout,
71+
value, scriptkey, spend_xpub
72+
} = deposit
73+
// Check if account xpub is valid.
74+
if (!signer.has_account(spend_xpub)) {
75+
throw new Error('account xpub is not recognized by master wallet')
76+
}
77+
// Define our pubkey as the deposit pubkey.
78+
const deposit_pk = signer.pubkey
79+
// Define our xpub as the return pubkey.
80+
const return_pk = parse_extkey(spend_xpub).pubkey
9181
// Get the context object for our deposit account.
92-
const ctx = get_deposit_ctx(agent_pk, pub, sequence)
82+
const ctx = get_deposit_ctx(agent_pk, deposit_pk, return_pk, sequence)
9383
// Define utxo object from deposit data.
9484
const utxo = { txid, vout, value, scriptkey }
9585
// Create a covenant with the contract and deposit.
96-
return create_covenant(ctx, contract, client._signer, utxo)
86+
return create_covenant(ctx, contract, signer._signer, utxo)
9787
}
9888
}
9989

100-
export function close_deposit_api (client : EscrowSigner) {
90+
export function close_deposit_api (signer : EscrowSigner) {
10191
return async (
10292
deposit : DepositData,
10393
txfee : number,
10494
address ?: string
105-
) : Promise<ReturnData> => {
106-
// Unpack client object.
95+
) : Promise<string> => {
96+
// Unpack signer object.
10797
const { txid } = deposit
10898
if (address === undefined) {
10999
// Compute an index value from the deposit txid.
110100
const acct = Buff.hex(txid).slice(0, 4).num
111101
// Generate refund address.
112-
address = client._wallet.get_account(acct).new_address()
102+
address = signer.get_account(acct).new_address()
113103
}
114104
// Create the return transaction.
115-
return create_return(address, deposit, client._signer, txfee)
105+
return create_return_psig(deposit, signer._signer, txfee)
116106
}
117107
}
118108

119-
export default function (client : EscrowSigner) {
109+
export default function (signer : EscrowSigner) {
120110
return {
121-
request_account : request_account_api(client),
122-
verify_account : verify_account_api(client),
123-
register_utxo : register_utxo_api(client),
124-
commit_utxo : commit_utxo_api(client),
125-
commit_deposit : commit_deposit_api(client),
126-
close_deposit : close_deposit_api(client)
111+
request_account : request_account_api(signer),
112+
verify_account : verify_account_api(signer),
113+
close_account : close_deposit_api(signer),
114+
commit_utxo : commit_utxo_api(signer),
115+
commit_deposit : commit_deposit_api(signer)
127116
}
128117
}

src/client/class/signer.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ export class EscrowSigner {
7171
return this._host_pub
7272
}
7373

74+
get network () {
75+
return this._client.network
76+
}
77+
7478
get pubkey () {
7579
return this._signer.pubkey
7680
}
@@ -81,6 +85,15 @@ export class EscrowSigner {
8185
request = request_api(this)
8286
witness = witness_api(this)
8387

88+
has_account (xpub : string) {
89+
return this._wallet.has_account(xpub)
90+
}
91+
92+
get_account (idx ?: number) {
93+
idx = idx ?? this._gen_idx()
94+
return this._wallet.get_account(idx)
95+
}
96+
8497
save (password : string) {
8598
const pass = Buff.str(password)
8699
const encdata = this._signer.backup(pass)

src/client/validators/deposit.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { parse_extkey } from '@cmdcode/crypto-tools/hd'
2+
import { verify_sig } from '@cmdcode/crypto-tools/signer'
3+
import { EscrowSigner } from '@/client/index.js'
4+
import { get_object_id } from '@/lib/util.js'
5+
6+
import {
7+
get_deposit_address,
8+
get_deposit_ctx
9+
} from '@/lib/deposit.js'
10+
11+
import { DepositAccount } from '@/types/index.js'
12+
13+
import * as assert from '@/assert.js'
14+
15+
export function verify_account (
16+
account : DepositAccount,
17+
signer : EscrowSigner
18+
) {
19+
const { acct_id, acct_sig, ...rest } = account
20+
const { host_pub, network, pubkey } = signer
21+
22+
const {
23+
address, agent_pk, deposit_pk,
24+
sequence, spend_xpub
25+
} = rest
26+
27+
assert.ok(host_pub !== undefined, 'host pubkey is not set on device')
28+
assert.ok(pubkey === deposit_pk, 'deposit pubkey does not match device')
29+
assert.ok(signer.has_account(spend_xpub), 'account xpub is not recognized by master wallet')
30+
31+
const return_pk = parse_extkey(spend_xpub).pubkey
32+
const context = get_deposit_ctx(agent_pk, deposit_pk, return_pk, sequence)
33+
const depo_addr = get_deposit_address(context, network)
34+
const digest = get_object_id(rest)
35+
36+
assert.ok(address === depo_addr, 'account address does not match context')
37+
assert.ok(digest.hex === acct_id, 'account id does not match digest')
38+
39+
verify_sig(acct_sig, acct_id, host_pub, { throws : true })
40+
}

0 commit comments

Comments
 (0)