mirror of
https://github.com/aljazceru/ark.git
synced 2025-12-17 12:14:21 +01:00
Add support for Out Of Round txs (#359)
* [common] rework address encoding * new address encoding * replace offchain address by vtxo output key in DB * merge migrations files into init one * fix txbuilder fixtures * fix transaction events * OOR scheme * fix conflicts * [sdk] OOR * update WASM wrappers * revert renaming * revert API changes * update parser.go * fix vtxosToTxsCovenantless * add settled and spent in Utxo and Transaction * Fixes (#5) * Revert unneeded changes and rename claim to settle * Revert changes to wasm and rename claim to settle --------- Co-authored-by: Pietralberto Mazza <18440657+altafan@users.noreply.github.com>
This commit is contained in:
@@ -1070,7 +1070,7 @@
|
|||||||
"swept": {
|
"swept": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"pending": {
|
"isOor": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"redeemTx": {
|
"redeemTx": {
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ message Vtxo {
|
|||||||
string spent_by = 4;
|
string spent_by = 4;
|
||||||
int64 expire_at = 5;
|
int64 expire_at = 5;
|
||||||
bool swept = 6;
|
bool swept = 6;
|
||||||
bool pending = 7;
|
bool is_oor = 7;
|
||||||
string redeem_tx = 8;
|
string redeem_tx = 8;
|
||||||
uint64 amount = 9;
|
uint64 amount = 9;
|
||||||
string pubkey = 10;
|
string pubkey = 10;
|
||||||
|
|||||||
@@ -2436,7 +2436,7 @@ type Vtxo struct {
|
|||||||
SpentBy string `protobuf:"bytes,4,opt,name=spent_by,json=spentBy,proto3" json:"spent_by,omitempty"`
|
SpentBy string `protobuf:"bytes,4,opt,name=spent_by,json=spentBy,proto3" json:"spent_by,omitempty"`
|
||||||
ExpireAt int64 `protobuf:"varint,5,opt,name=expire_at,json=expireAt,proto3" json:"expire_at,omitempty"`
|
ExpireAt int64 `protobuf:"varint,5,opt,name=expire_at,json=expireAt,proto3" json:"expire_at,omitempty"`
|
||||||
Swept bool `protobuf:"varint,6,opt,name=swept,proto3" json:"swept,omitempty"`
|
Swept bool `protobuf:"varint,6,opt,name=swept,proto3" json:"swept,omitempty"`
|
||||||
Pending bool `protobuf:"varint,7,opt,name=pending,proto3" json:"pending,omitempty"`
|
IsOor bool `protobuf:"varint,7,opt,name=is_oor,json=isOor,proto3" json:"is_oor,omitempty"`
|
||||||
RedeemTx string `protobuf:"bytes,8,opt,name=redeem_tx,json=redeemTx,proto3" json:"redeem_tx,omitempty"`
|
RedeemTx string `protobuf:"bytes,8,opt,name=redeem_tx,json=redeemTx,proto3" json:"redeem_tx,omitempty"`
|
||||||
Amount uint64 `protobuf:"varint,9,opt,name=amount,proto3" json:"amount,omitempty"`
|
Amount uint64 `protobuf:"varint,9,opt,name=amount,proto3" json:"amount,omitempty"`
|
||||||
Pubkey string `protobuf:"bytes,10,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
|
Pubkey string `protobuf:"bytes,10,opt,name=pubkey,proto3" json:"pubkey,omitempty"`
|
||||||
@@ -2516,9 +2516,9 @@ func (x *Vtxo) GetSwept() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Vtxo) GetPending() bool {
|
func (x *Vtxo) GetIsOor() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Pending
|
return x.IsOor
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -3067,7 +3067,7 @@ var file_ark_v1_service_proto_rawDesc = []byte{
|
|||||||
0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01,
|
0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
0x28, 0x09, 0x52, 0x02, 0x74, 0x78, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
||||||
0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72,
|
0x5f, 0x74, 0x78, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x72,
|
||||||
0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0x9e, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f,
|
0x65, 0x6e, 0x74, 0x54, 0x78, 0x69, 0x64, 0x22, 0x9b, 0x02, 0x0a, 0x04, 0x56, 0x74, 0x78, 0x6f,
|
||||||
0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
0x12, 0x2c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70,
|
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70,
|
||||||
0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14,
|
0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x14,
|
||||||
@@ -3079,177 +3079,177 @@ var file_ark_v1_service_proto_rawDesc = []byte{
|
|||||||
0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
|
0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||||
0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73,
|
0x03, 0x52, 0x08, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73,
|
||||||
0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70,
|
0x77, 0x65, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x73, 0x77, 0x65, 0x70,
|
||||||
0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01,
|
0x74, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x73, 0x5f, 0x6f, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||||
0x28, 0x08, 0x52, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x72,
|
0x08, 0x52, 0x05, 0x69, 0x73, 0x4f, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x65,
|
||||||
0x65, 0x64, 0x65, 0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
0x65, 0x6d, 0x5f, 0x74, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x64,
|
||||||
0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75,
|
0x65, 0x65, 0x6d, 0x54, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18,
|
||||||
0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
|
0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09,
|
0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70,
|
||||||
0x52, 0x06, 0x70, 0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x54,
|
0x75, 0x62, 0x6b, 0x65, 0x79, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e,
|
||||||
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61,
|
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65,
|
||||||
0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61,
|
||||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65,
|
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52,
|
||||||
0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, 0x6f,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
||||||
0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
||||||
0x76, 0x31, 0x2e, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
|
0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x06,
|
0x48, 0x00, 0x52, 0x05, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x64,
|
||||||
0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61,
|
0x65, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e,
|
0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||||
0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65,
|
0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x42, 0x04,
|
||||||
0x6d, 0x42, 0x04, 0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x6e,
|
0x0a, 0x02, 0x74, 0x78, 0x22, 0xd8, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x72,
|
||||||
0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04,
|
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69,
|
||||||
0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64,
|
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a,
|
||||||
0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18,
|
0x0b, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03,
|
||||||
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f,
|
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70,
|
||||||
0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74,
|
0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73,
|
||||||
0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65,
|
0x12, 0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74,
|
||||||
0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61,
|
0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e,
|
0x76, 0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62,
|
||||||
0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x16, 0x63, 0x6c,
|
0x6c, 0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x46, 0x0a, 0x16, 0x63, 0x6c, 0x61, 0x69, 0x6d,
|
||||||
0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75,
|
0x65, 0x64, 0x5f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x75, 0x74, 0x78, 0x6f,
|
||||||
0x74, 0x78, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b,
|
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||||
0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x14, 0x63, 0x6c,
|
0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x14, 0x63, 0x6c, 0x61, 0x69, 0x6d,
|
||||||
0x61, 0x69, 0x6d, 0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78,
|
0x65, 0x64, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22,
|
||||||
0x6f, 0x73, 0x22, 0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61,
|
0x91, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
|
||||||
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64,
|
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b,
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x31, 0x0a, 0x0b, 0x73, 0x70, 0x65,
|
||||||
0x73, 0x70, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
0x6e, 0x74, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10,
|
||||||
0x0b, 0x32, 0x10, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f,
|
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
0x69, 0x6e, 0x74, 0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12,
|
0x52, 0x0a, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x35, 0x0a, 0x0f,
|
||||||
0x35, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78,
|
0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x18,
|
||||||
0x6f, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x56,
|
||||||
0x31, 0x2e, 0x56, 0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c,
|
0x74, 0x78, 0x6f, 0x52, 0x0e, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x56, 0x74,
|
||||||
0x65, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x2a, 0x98, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
0x78, 0x6f, 0x73, 0x2a, 0x98, 0x01, 0x0a, 0x0a, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61,
|
||||||
0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53,
|
0x67, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47,
|
||||||
0x54, 0x41, 0x47, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
|
0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
|
||||||
0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47,
|
0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x52,
|
||||||
0x45, 0x5f, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01,
|
0x45, 0x47, 0x49, 0x53, 0x54, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x1c, 0x0a,
|
||||||
0x12, 0x1c, 0x0a, 0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f,
|
0x18, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e,
|
||||||
0x46, 0x49, 0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x19,
|
0x41, 0x4c, 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x52,
|
||||||
0x0a, 0x15, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49,
|
0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x41, 0x4c,
|
||||||
0x4e, 0x41, 0x4c, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x55,
|
0x49, 0x5a, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f,
|
||||||
0x4e, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10,
|
0x53, 0x54, 0x41, 0x47, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x32, 0xeb,
|
||||||
0x04, 0x32, 0xeb, 0x0d, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
0x0d, 0x0a, 0x0a, 0x41, 0x72, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a,
|
||||||
0x12, 0x4c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72,
|
0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75,
|
0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
|
0x1a, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66,
|
||||||
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3,
|
0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02,
|
||||||
0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74,
|
0x0a, 0x12, 0x08, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47,
|
||||||
0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64,
|
0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||||
0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
|
0x73, 0x12, 0x21, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f,
|
||||||
|
0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
|
||||||
0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11,
|
||||||
0x2e, 0x47, 0x65, 0x74, 0x42, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, 0x72,
|
0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x69, 0x6e,
|
||||||
0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4,
|
0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e,
|
||||||
0x93, 0x02, 0x11, 0x3a, 0x01, 0x2a, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x61, 0x72,
|
|
||||||
0x64, 0x69, 0x6e, 0x67, 0x12, 0x98, 0x01, 0x0a, 0x1a, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
|
||||||
0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f,
|
|
||||||
0x75, 0x6e, 0x64, 0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67,
|
|
||||||
0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65,
|
|
||||||
0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a,
|
|
||||||
0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
|
|
||||||
0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75,
|
|
||||||
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93,
|
|
||||||
0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
|
||||||
0x2f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12,
|
|
||||||
0x9c, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70,
|
|
||||||
0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12,
|
|
||||||
0x2a, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
|
|
||||||
0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72,
|
|
||||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74,
|
|
||||||
0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e,
|
0x12, 0x29, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||||
0x3a, 0x01, 0x2a, 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72,
|
0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52,
|
||||||
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d,
|
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x61, 0x72,
|
||||||
0x0a, 0x10, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63,
|
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70,
|
||||||
0x65, 0x73, 0x12, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d,
|
0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52,
|
||||||
0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62,
|
0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65,
|
||||||
0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73,
|
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x9c, 0x01, 0x0a,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a,
|
0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73,
|
||||||
0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65,
|
0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x61,
|
||||||
0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01,
|
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75,
|
||||||
0x0a, 0x14, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e,
|
0x74, 0x70, 0x75, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e,
|
||||||
0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||||
0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74,
|
0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
|
||||||
0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72,
|
0x73, 0x46, 0x6f, 0x72, 0x4e, 0x65, 0x78, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73,
|
||||||
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53,
|
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x3a, 0x01, 0x2a,
|
||||||
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x72, 0x65, 0x67, 0x69,
|
||||||
0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76,
|
0x73, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12, 0x7d, 0x0a, 0x10, 0x53,
|
||||||
0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62,
|
0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12,
|
||||||
0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01,
|
0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54,
|
||||||
0x0a, 0x16, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f,
|
0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
0x1a, 0x20, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
|
||||||
0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f,
|
0x54, 0x72, 0x65, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, 0x2a, 0x22, 0x1b, 0x2f,
|
||||||
0x26, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53,
|
0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75,
|
||||||
0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52,
|
0x62, 0x6d, 0x69, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x8d, 0x01, 0x0a, 0x14, 0x53,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a,
|
0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||||
0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75,
|
0x72, 0x65, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62,
|
||||||
0x62, 0x6d, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x6b,
|
0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||||
0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
||||||
0x12, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65,
|
0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x69, 0x67, 0x6e,
|
||||||
0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a,
|
||||||
0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e,
|
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x3a, 0x01, 0x2a, 0x22, 0x1f, 0x2f, 0x76, 0x31, 0x2f, 0x72,
|
||||||
0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74,
|
||||||
0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75,
|
0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x16, 0x53,
|
||||||
0x6e, 0x64, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x04, 0x50,
|
0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65,
|
||||||
0x69, 0x6e, 0x67, 0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e,
|
0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53,
|
||||||
0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76,
|
0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65,
|
||||||
0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23,
|
0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x61,
|
||||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e,
|
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x53, 0x69, 0x67, 0x6e,
|
||||||
0x64, 0x2f, 0x70, 0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f,
|
0x65, 0x64, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x52, 0x65, 0x73, 0x70,
|
||||||
0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79,
|
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22,
|
||||||
0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72,
|
0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69,
|
||||||
0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x74, 0x46, 0x6f, 0x72, 0x66, 0x65, 0x69, 0x74, 0x54, 0x78, 0x73, 0x12, 0x6b, 0x0a, 0x0e, 0x47,
|
||||||
0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
|
0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e,
|
||||||
0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53,
|
||||||
0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x76,
|
0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61,
|
||||||
0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x73, 0x0a, 0x0f, 0x43, 0x6f, 0x6d,
|
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74,
|
||||||
0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x61,
|
0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3,
|
||||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61,
|
0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f,
|
||||||
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61,
|
0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67,
|
||||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61,
|
0x12, 0x13, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65,
|
||||||
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x50,
|
||||||
0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61,
|
0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4,
|
||||||
0x79, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x57,
|
0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x70,
|
||||||
0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, 0x72, 0x6b,
|
0x69, 0x6e, 0x67, 0x2f, 0x7b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x7d,
|
||||||
0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
0x12, 0x64, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e,
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
|
0x74, 0x12, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||||
0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82,
|
0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64,
|
0x1d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50,
|
||||||
0x2f, 0x7b, 0x74, 0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x6f,
|
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16,
|
||||||
0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x3a, 0x01, 0x2a, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x70,
|
||||||
0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71,
|
0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x73, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
|
0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||||
0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65,
|
||||||
0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f,
|
0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||||
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x5d, 0x0a,
|
0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65,
|
||||||
0x09, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b,
|
0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93,
|
||||||
0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71,
|
0x02, 0x19, 0x3a, 0x01, 0x2a, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x79, 0x6d, 0x65,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69,
|
0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x57, 0x0a, 0x08, 0x47,
|
||||||
0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x17, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||||
0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78,
|
0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x6f, 0x73, 0x2f, 0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, 0x01, 0x0a,
|
0x1a, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75,
|
||||||
0x15, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93,
|
||||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e,
|
0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x7b, 0x74,
|
||||||
0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53,
|
0x78, 0x69, 0x64, 0x7d, 0x12, 0x64, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64,
|
||||||
0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61,
|
0x42, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65,
|
||||||
0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
0x74, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f,
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31,
|
0x75, 0x6e, 0x64, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x42,
|
0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x6f, 0x75,
|
||||||
0x92, 0x01, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c,
|
0x6e, 0x64, 0x2f, 0x69, 0x64, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x5d, 0x0a, 0x09, 0x4c, 0x69,
|
||||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d,
|
0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31,
|
||||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e,
|
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73,
|
0x74, 0x1a, 0x19, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56,
|
||||||
0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e,
|
0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3,
|
||||||
0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03,
|
0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x74, 0x78, 0x6f, 0x73, 0x2f,
|
||||||
0x41, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41,
|
0x7b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x15, 0x47, 0x65,
|
||||||
0x72, 0x6b, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47,
|
0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72,
|
||||||
0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b,
|
0x65, 0x61, 0x6d, 0x12, 0x24, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
|
||||||
0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65,
|
||||||
|
0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x61, 0x72, 0x6b, 0x2e,
|
||||||
|
0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
|
0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72,
|
||||||
|
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x30, 0x01, 0x42, 0x92, 0x01, 0x0a,
|
||||||
|
0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x61, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x65, 0x72,
|
||||||
|
0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3d, 0x67, 0x69, 0x74,
|
||||||
|
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x72, 0x6b, 0x2d, 0x6e, 0x65, 0x74, 0x77,
|
||||||
|
0x6f, 0x72, 0x6b, 0x2f, 0x61, 0x72, 0x6b, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63,
|
||||||
|
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x72,
|
||||||
|
0x6b, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x72, 0x6b, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58,
|
||||||
|
0xaa, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x06, 0x41, 0x72, 0x6b, 0x5c,
|
||||||
|
0x56, 0x31, 0xe2, 0x02, 0x12, 0x41, 0x72, 0x6b, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d,
|
||||||
|
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x41, 0x72, 0x6b, 0x3a, 0x3a, 0x56,
|
||||||
|
0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func main() {
|
|||||||
&configCommand,
|
&configCommand,
|
||||||
&dumpCommand,
|
&dumpCommand,
|
||||||
&receiveCommand,
|
&receiveCommand,
|
||||||
&claimCmd,
|
&settleCmd,
|
||||||
&sendCommand,
|
&sendCommand,
|
||||||
&balanceCommand,
|
&balanceCommand,
|
||||||
&redeemCommand,
|
&redeemCommand,
|
||||||
@@ -160,11 +160,11 @@ var (
|
|||||||
return receive(ctx)
|
return receive(ctx)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
claimCmd = cli.Command{
|
settleCmd = cli.Command{
|
||||||
Name: "claim",
|
Name: "settle",
|
||||||
Usage: "Claim onboarding funds or pending payments",
|
Usage: "Settle onboarding funds or oor payments",
|
||||||
Action: func(ctx *cli.Context) error {
|
Action: func(ctx *cli.Context) error {
|
||||||
return claim(ctx)
|
return settle(ctx)
|
||||||
},
|
},
|
||||||
Flags: []cli.Flag{passwordFlag},
|
Flags: []cli.Flag{passwordFlag},
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,7 @@ func receive(ctx *cli.Context) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func claim(ctx *cli.Context) error {
|
func settle(ctx *cli.Context) error {
|
||||||
password, err := readPassword(ctx)
|
password, err := readPassword(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -275,7 +275,7 @@ func claim(ctx *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
txID, err := arkSdkClient.Claim(ctx.Context)
|
txID, err := arkSdkClient.Settle(ctx.Context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,20 +15,17 @@ import (
|
|||||||
type VtxoScript common.VtxoScript[bitcoinTapTree]
|
type VtxoScript common.VtxoScript[bitcoinTapTree]
|
||||||
|
|
||||||
func ParseVtxoScript(desc string) (VtxoScript, error) {
|
func ParseVtxoScript(desc string) (VtxoScript, error) {
|
||||||
v := &DefaultVtxoScript{}
|
types := []VtxoScript{
|
||||||
// TODO add other type
|
&DefaultVtxoScript{},
|
||||||
err := v.FromDescriptor(desc)
|
|
||||||
if err != nil {
|
|
||||||
v := &ReversibleVtxoScript{}
|
|
||||||
err = v.FromDescriptor(desc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid vtxo descriptor: %s", desc)
|
|
||||||
}
|
|
||||||
|
|
||||||
return v, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return v, nil
|
for _, v := range types {
|
||||||
|
if err := v.FromDescriptor(desc); err == nil {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("invalid vtxo descriptor: %s", desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -101,94 +98,6 @@ func (v *DefaultVtxoScript) TapTree() (*secp256k1.PublicKey, bitcoinTapTree, err
|
|||||||
return taprootKey, bitcoinTapTree{tapTree}, nil
|
return taprootKey, bitcoinTapTree{tapTree}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* ReversibleVtxoScript allows sender of the VTXO to revert the transaction
|
|
||||||
* unilateral exit is in favor of the sender
|
|
||||||
* - Owner and ASP (forfeit owner)
|
|
||||||
* - Sender and ASP (forfeit sender)
|
|
||||||
* - Sender after t (unilateral exit)
|
|
||||||
*/
|
|
||||||
type ReversibleVtxoScript struct {
|
|
||||||
Asp *secp256k1.PublicKey
|
|
||||||
Sender *secp256k1.PublicKey
|
|
||||||
Owner *secp256k1.PublicKey
|
|
||||||
ExitDelay uint
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ReversibleVtxoScript) ToDescriptor() string {
|
|
||||||
owner := hex.EncodeToString(schnorr.SerializePubKey(v.Owner))
|
|
||||||
sender := hex.EncodeToString(schnorr.SerializePubKey(v.Sender))
|
|
||||||
asp := hex.EncodeToString(schnorr.SerializePubKey(v.Asp))
|
|
||||||
|
|
||||||
return fmt.Sprintf(
|
|
||||||
descriptor.ReversibleVtxoScriptTemplate,
|
|
||||||
hex.EncodeToString(UnspendableKey().SerializeCompressed()),
|
|
||||||
sender,
|
|
||||||
asp,
|
|
||||||
v.ExitDelay,
|
|
||||||
sender,
|
|
||||||
owner,
|
|
||||||
asp,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ReversibleVtxoScript) FromDescriptor(desc string) error {
|
|
||||||
owner, sender, asp, exitDelay, err := descriptor.ParseReversibleVtxoDescriptor(desc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
v.Owner = owner
|
|
||||||
v.Sender = sender
|
|
||||||
v.Asp = asp
|
|
||||||
v.ExitDelay = exitDelay
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *ReversibleVtxoScript) TapTree() (*secp256k1.PublicKey, bitcoinTapTree, error) {
|
|
||||||
redeemClosure := &CSVSigClosure{
|
|
||||||
Pubkey: v.Sender,
|
|
||||||
Seconds: v.ExitDelay,
|
|
||||||
}
|
|
||||||
|
|
||||||
redeemLeaf, err := redeemClosure.Leaf()
|
|
||||||
if err != nil {
|
|
||||||
return nil, bitcoinTapTree{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
forfeitClosure := &MultisigClosure{
|
|
||||||
Pubkey: v.Owner,
|
|
||||||
AspPubkey: v.Asp,
|
|
||||||
}
|
|
||||||
|
|
||||||
forfeitLeaf, err := forfeitClosure.Leaf()
|
|
||||||
if err != nil {
|
|
||||||
return nil, bitcoinTapTree{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
reverseForfeitClosure := &MultisigClosure{
|
|
||||||
Pubkey: v.Sender,
|
|
||||||
AspPubkey: v.Asp,
|
|
||||||
}
|
|
||||||
|
|
||||||
reverseForfeitLeaf, err := reverseForfeitClosure.Leaf()
|
|
||||||
if err != nil {
|
|
||||||
return nil, bitcoinTapTree{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tapTree := txscript.AssembleTaprootScriptTree(
|
|
||||||
*redeemLeaf, *forfeitLeaf, *reverseForfeitLeaf,
|
|
||||||
)
|
|
||||||
|
|
||||||
root := tapTree.RootNode.TapHash()
|
|
||||||
taprootKey := txscript.ComputeTaprootOutputKey(
|
|
||||||
UnspendableKey(),
|
|
||||||
root[:],
|
|
||||||
)
|
|
||||||
|
|
||||||
return taprootKey, bitcoinTapTree{tapTree}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// bitcoinTapTree is a wrapper around txscript.IndexedTapScriptTree to implement the common.TaprootTree interface
|
// bitcoinTapTree is a wrapper around txscript.IndexedTapScriptTree to implement the common.TaprootTree interface
|
||||||
type bitcoinTapTree struct {
|
type bitcoinTapTree struct {
|
||||||
*txscript.IndexedTapScriptTree
|
*txscript.IndexedTapScriptTree
|
||||||
|
|||||||
@@ -19,12 +19,8 @@ func TestParseDescriptor(t *testing.T) {
|
|||||||
aliceKey, err := secp256k1.GeneratePrivateKey()
|
aliceKey, err := secp256k1.GeneratePrivateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
bobKey, err := secp256k1.GeneratePrivateKey()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
aspPubKey := hex.EncodeToString(schnorr.SerializePubKey(aspKey.PubKey()))
|
aspPubKey := hex.EncodeToString(schnorr.SerializePubKey(aspKey.PubKey()))
|
||||||
alicePubKey := hex.EncodeToString(schnorr.SerializePubKey(aliceKey.PubKey()))
|
alicePubKey := hex.EncodeToString(schnorr.SerializePubKey(aliceKey.PubKey()))
|
||||||
bobPubKey := hex.EncodeToString(schnorr.SerializePubKey(bobKey.PubKey()))
|
|
||||||
|
|
||||||
unspendableKey := hex.EncodeToString(bitcointree.UnspendableKey().SerializeCompressed())
|
unspendableKey := hex.EncodeToString(bitcointree.UnspendableKey().SerializeCompressed())
|
||||||
|
|
||||||
@@ -44,24 +40,4 @@ func TestParseDescriptor(t *testing.T) {
|
|||||||
require.Equal(t, defaultScriptDescriptor, vtxo.ToDescriptor())
|
require.Equal(t, defaultScriptDescriptor, vtxo.ToDescriptor())
|
||||||
require.Equal(t, alicePubKey, hex.EncodeToString(schnorr.SerializePubKey(vtxo.(*bitcointree.DefaultVtxoScript).Owner)))
|
require.Equal(t, alicePubKey, hex.EncodeToString(schnorr.SerializePubKey(vtxo.(*bitcointree.DefaultVtxoScript).Owner)))
|
||||||
require.Equal(t, aspPubKey, hex.EncodeToString(schnorr.SerializePubKey(vtxo.(*bitcointree.DefaultVtxoScript).Asp)))
|
require.Equal(t, aspPubKey, hex.EncodeToString(schnorr.SerializePubKey(vtxo.(*bitcointree.DefaultVtxoScript).Asp)))
|
||||||
|
|
||||||
reversibleScriptDescriptor := fmt.Sprintf(
|
|
||||||
descriptor.ReversibleVtxoScriptTemplate,
|
|
||||||
unspendableKey,
|
|
||||||
alicePubKey,
|
|
||||||
aspPubKey,
|
|
||||||
512,
|
|
||||||
alicePubKey,
|
|
||||||
bobPubKey,
|
|
||||||
aspPubKey,
|
|
||||||
)
|
|
||||||
|
|
||||||
vtxo, err = bitcointree.ParseVtxoScript(reversibleScriptDescriptor)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.IsType(t, &bitcointree.ReversibleVtxoScript{}, vtxo)
|
|
||||||
require.Equal(t, reversibleScriptDescriptor, vtxo.ToDescriptor())
|
|
||||||
require.Equal(t, alicePubKey, hex.EncodeToString(schnorr.SerializePubKey(vtxo.(*bitcointree.ReversibleVtxoScript).Sender)))
|
|
||||||
require.Equal(t, bobPubKey, hex.EncodeToString(schnorr.SerializePubKey(vtxo.(*bitcointree.ReversibleVtxoScript).Owner)))
|
|
||||||
require.Equal(t, aspPubKey, hex.EncodeToString(schnorr.SerializePubKey(vtxo.(*bitcointree.ReversibleVtxoScript).Asp)))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,91 +11,6 @@ import (
|
|||||||
// tr(unspendable, { and(pk(user), pk(asp)), and(older(timeout), pk(user)) })
|
// tr(unspendable, { and(pk(user), pk(asp)), and(older(timeout), pk(user)) })
|
||||||
const DefaultVtxoDescriptorTemplate = "tr(%s,{ and(pk(%s), pk(%s)), and(older(%d), pk(%s)) })"
|
const DefaultVtxoDescriptorTemplate = "tr(%s,{ and(pk(%s), pk(%s)), and(older(%d), pk(%s)) })"
|
||||||
|
|
||||||
// tr(unspendable, { { and(pk(sender), pk(asp)), and(older(timeout), pk(sender)) }, and(pk(receiver), pk(asp)) })
|
|
||||||
const ReversibleVtxoScriptTemplate = "tr(%s,{ { and(pk(%s), pk(%s)), and(older(%d), pk(%s)) }, and(pk(%s), pk(%s)) })"
|
|
||||||
|
|
||||||
func ParseReversibleVtxoDescriptor(
|
|
||||||
descriptor string,
|
|
||||||
) (user, sender, asp *secp256k1.PublicKey, timeout uint, err error) {
|
|
||||||
desc, err := ParseTaprootDescriptor(descriptor)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(desc.ScriptTree) != 3 {
|
|
||||||
return nil, nil, nil, 0, errors.New("not a reversible vtxo script descriptor")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, leaf := range desc.ScriptTree {
|
|
||||||
if andLeaf, ok := leaf.(*And); ok {
|
|
||||||
if first, ok := andLeaf.First.(*PK); ok {
|
|
||||||
if second, ok := andLeaf.Second.(*PK); ok {
|
|
||||||
keyBytes, err := hex.DecodeString(first.Key.Hex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
if sender == nil {
|
|
||||||
sender, err = schnorr.ParsePubKey(keyBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
user, err = schnorr.ParsePubKey(keyBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if asp == nil {
|
|
||||||
keyBytes, err = hex.DecodeString(second.Key.Hex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
asp, err = schnorr.ParsePubKey(keyBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if first, ok := andLeaf.First.(*Older); ok {
|
|
||||||
if second, ok := andLeaf.Second.(*PK); ok {
|
|
||||||
timeout = first.Timeout
|
|
||||||
keyBytes, err := hex.DecodeString(second.Key.Hex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sender, err = schnorr.ParsePubKey(keyBytes)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if user == nil {
|
|
||||||
return nil, nil, nil, 0, errors.New("descriptor is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
if asp == nil {
|
|
||||||
return nil, nil, nil, 0, errors.New("descriptor is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
if timeout == 0 {
|
|
||||||
return nil, nil, nil, 0, errors.New("descriptor is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
if sender == nil {
|
|
||||||
return nil, nil, nil, 0, errors.New("descriptor is invalid")
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseDefaultVtxoDescriptor(
|
func ParseDefaultVtxoDescriptor(
|
||||||
descriptor string,
|
descriptor string,
|
||||||
) (user, asp *secp256k1.PublicKey, timeout uint, err error) {
|
) (user, asp *secp256k1.PublicKey, timeout uint, err error) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type ArkClient interface {
|
|||||||
ctx context.Context, addr string, amount uint64, withExpiryCoinselect bool,
|
ctx context.Context, addr string, amount uint64, withExpiryCoinselect bool,
|
||||||
) (string, error)
|
) (string, error)
|
||||||
SendAsync(ctx context.Context, withExpiryCoinselect bool, receivers []Receiver) (string, error)
|
SendAsync(ctx context.Context, withExpiryCoinselect bool, receivers []Receiver) (string, error)
|
||||||
Claim(ctx context.Context) (string, error)
|
Settle(ctx context.Context) (string, error)
|
||||||
ListVtxos(ctx context.Context) (spendable, spent []client.Vtxo, err error)
|
ListVtxos(ctx context.Context) (spendable, spent []client.Vtxo, err error)
|
||||||
Dump(ctx context.Context) (seed string, err error)
|
Dump(ctx context.Context) (seed string, err error)
|
||||||
GetTransactionHistory(ctx context.Context) ([]types.Transaction, error)
|
GetTransactionHistory(ctx context.Context) ([]types.Transaction, error)
|
||||||
|
|||||||
@@ -270,6 +270,27 @@ func (a *arkClient) ping(
|
|||||||
return ticker.Stop
|
return ticker.Stop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *arkClient) ListVtxos(
|
||||||
|
ctx context.Context,
|
||||||
|
) (spendableVtxos, spentVtxos []client.Vtxo, err error) {
|
||||||
|
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range offchainAddrs {
|
||||||
|
spendable, spent, err := a.client.ListVtxos(ctx, addr.Address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spendableVtxos = append(spendableVtxos, spendable...)
|
||||||
|
spentVtxos = append(spentVtxos, spent...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func getClient(
|
func getClient(
|
||||||
supportedClients utils.SupportedType[utils.ClientFactory], clientType, aspUrl string,
|
supportedClients utils.SupportedType[utils.ClientFactory], clientType, aspUrl string,
|
||||||
) (client.ASPClient, error) {
|
) (client.ASPClient, error) {
|
||||||
@@ -329,3 +350,15 @@ func getWalletStore(storeType, datadir string) (walletstore.WalletStore, error)
|
|||||||
func getCreatedAtFromExpiry(roundLifetime int64, expiry time.Time) time.Time {
|
func getCreatedAtFromExpiry(roundLifetime int64, expiry time.Time) time.Time {
|
||||||
return expiry.Add(-time.Duration(roundLifetime) * time.Second)
|
return expiry.Add(-time.Duration(roundLifetime) * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterByOutpoints(vtxos []client.Vtxo, outpoints []client.Outpoint) []client.Vtxo {
|
||||||
|
filtered := make([]client.Vtxo, 0, len(vtxos))
|
||||||
|
for _, vtxo := range vtxos {
|
||||||
|
for _, outpoint := range outpoints {
|
||||||
|
if vtxo.Outpoint.Equals(outpoint) {
|
||||||
|
filtered = append(filtered, vtxo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered
|
||||||
|
}
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ type Outpoint struct {
|
|||||||
VOut uint32
|
VOut uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o Outpoint) Equals(other Outpoint) bool {
|
||||||
|
return o.Txid == other.Txid && o.VOut == other.VOut
|
||||||
|
}
|
||||||
|
|
||||||
type Input struct {
|
type Input struct {
|
||||||
Outpoint
|
Outpoint
|
||||||
Descriptor string
|
Descriptor string
|
||||||
@@ -95,7 +99,7 @@ type Vtxo struct {
|
|||||||
RoundTxid string
|
RoundTxid string
|
||||||
ExpiresAt *time.Time
|
ExpiresAt *time.Time
|
||||||
RedeemTx string
|
RedeemTx string
|
||||||
Pending bool
|
IsOOR bool
|
||||||
SpentBy string
|
SpentBy string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ func (c *grpcClient) GetTransactionsStream(
|
|||||||
Round: &client.RoundTransaction{
|
Round: &client.RoundTransaction{
|
||||||
Txid: tx.Round.Txid,
|
Txid: tx.Round.Txid,
|
||||||
SpentVtxos: outpointsFromProto(tx.Round.SpentVtxos),
|
SpentVtxos: outpointsFromProto(tx.Round.SpentVtxos),
|
||||||
SpendableVtxos: vtxosFromProto(tx.Round.SpendableVtxos),
|
SpendableVtxos: vtxos(tx.Round.SpendableVtxos).toVtxos(),
|
||||||
ClaimedBoardingUtxos: outpointsFromProto(tx.Round.ClaimedBoardingUtxos),
|
ClaimedBoardingUtxos: outpointsFromProto(tx.Round.ClaimedBoardingUtxos),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ func (c *grpcClient) GetTransactionsStream(
|
|||||||
Redeem: &client.RedeemTransaction{
|
Redeem: &client.RedeemTransaction{
|
||||||
Txid: tx.Redeem.Txid,
|
Txid: tx.Redeem.Txid,
|
||||||
SpentVtxos: outpointsFromProto(tx.Redeem.SpentVtxos),
|
SpentVtxos: outpointsFromProto(tx.Redeem.SpentVtxos),
|
||||||
SpendableVtxos: vtxosFromProto(tx.Redeem.SpendableVtxos),
|
SpendableVtxos: vtxos(tx.Redeem.SpendableVtxos).toVtxos(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -394,24 +394,3 @@ func outpointsFromProto(protoOutpoints []*arkv1.Outpoint) []client.Outpoint {
|
|||||||
}
|
}
|
||||||
return outpoints
|
return outpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
func vtxosFromProto(protoVtxos []*arkv1.Vtxo) []client.Vtxo {
|
|
||||||
vtxos := make([]client.Vtxo, len(protoVtxos))
|
|
||||||
for i, v := range protoVtxos {
|
|
||||||
expiresAt := time.Unix(v.ExpireAt, 0)
|
|
||||||
vtxos[i] = client.Vtxo{
|
|
||||||
Outpoint: client.Outpoint{
|
|
||||||
Txid: v.Outpoint.Txid,
|
|
||||||
VOut: v.Outpoint.Vout,
|
|
||||||
},
|
|
||||||
Pubkey: v.Pubkey,
|
|
||||||
Amount: v.Amount,
|
|
||||||
RoundTxid: v.RoundTxid,
|
|
||||||
ExpiresAt: &expiresAt,
|
|
||||||
RedeemTx: v.RedeemTx,
|
|
||||||
Pending: v.Pending,
|
|
||||||
SpentBy: v.SpentBy,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return vtxos
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func (v vtxo) toVtxo() client.Vtxo {
|
|||||||
Amount: v.GetAmount(),
|
Amount: v.GetAmount(),
|
||||||
RoundTxid: v.GetRoundTxid(),
|
RoundTxid: v.GetRoundTxid(),
|
||||||
ExpiresAt: expiresAt,
|
ExpiresAt: expiresAt,
|
||||||
Pending: v.GetPending(),
|
IsOOR: v.GetIsOor(),
|
||||||
RedeemTx: v.GetRedeemTx(),
|
RedeemTx: v.GetRedeemTx(),
|
||||||
SpentBy: v.GetSpentBy(),
|
SpentBy: v.GetSpentBy(),
|
||||||
Pubkey: v.GetPubkey(),
|
Pubkey: v.GetPubkey(),
|
||||||
|
|||||||
@@ -499,7 +499,7 @@ func (a *restClient) ListVtxos(
|
|||||||
Amount: uint64(amount),
|
Amount: uint64(amount),
|
||||||
RoundTxid: v.RoundTxid,
|
RoundTxid: v.RoundTxid,
|
||||||
ExpiresAt: expiresAt,
|
ExpiresAt: expiresAt,
|
||||||
Pending: v.Pending,
|
IsOOR: v.IsOor,
|
||||||
RedeemTx: v.RedeemTx,
|
RedeemTx: v.RedeemTx,
|
||||||
SpentBy: v.SpentBy,
|
SpentBy: v.SpentBy,
|
||||||
Pubkey: v.Pubkey,
|
Pubkey: v.Pubkey,
|
||||||
@@ -701,7 +701,7 @@ func vtxosFromRest(restVtxos []*models.V1Vtxo) []client.Vtxo {
|
|||||||
RoundTxid: v.RoundTxid,
|
RoundTxid: v.RoundTxid,
|
||||||
ExpiresAt: expiresAt,
|
ExpiresAt: expiresAt,
|
||||||
RedeemTx: v.RedeemTx,
|
RedeemTx: v.RedeemTx,
|
||||||
Pending: v.Pending,
|
IsOOR: v.IsOor,
|
||||||
SpentBy: v.SpentBy,
|
SpentBy: v.SpentBy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ type V1Vtxo struct {
|
|||||||
// expire at
|
// expire at
|
||||||
ExpireAt string `json:"expireAt,omitempty"`
|
ExpireAt string `json:"expireAt,omitempty"`
|
||||||
|
|
||||||
|
// is oor
|
||||||
|
IsOor bool `json:"isOor,omitempty"`
|
||||||
|
|
||||||
// outpoint
|
// outpoint
|
||||||
Outpoint *V1Outpoint `json:"outpoint,omitempty"`
|
Outpoint *V1Outpoint `json:"outpoint,omitempty"`
|
||||||
|
|
||||||
// pending
|
|
||||||
Pending bool `json:"pending,omitempty"`
|
|
||||||
|
|
||||||
// pubkey
|
// pubkey
|
||||||
Pubkey string `json:"pubkey,omitempty"`
|
Pubkey string `json:"pubkey,omitempty"`
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 1000,
|
Amount: 1000,
|
||||||
Type: sdktypes.TxSent,
|
Type: sdktypes.TxSent,
|
||||||
IsPending: false,
|
|
||||||
CreatedAt: time.Unix(1726054898, 0),
|
CreatedAt: time.Unix(1726054898, 0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -48,7 +47,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 1000,
|
Amount: 1000,
|
||||||
Type: sdktypes.TxReceived,
|
Type: sdktypes.TxReceived,
|
||||||
IsPending: true,
|
|
||||||
CreatedAt: time.Unix(1726054898, 0),
|
CreatedAt: time.Unix(1726054898, 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -57,7 +55,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 2000,
|
Amount: 2000,
|
||||||
Type: sdktypes.TxReceived,
|
Type: sdktypes.TxReceived,
|
||||||
IsPending: true,
|
|
||||||
CreatedAt: time.Unix(1726486359, 0),
|
CreatedAt: time.Unix(1726486359, 0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -72,7 +69,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 1000,
|
Amount: 1000,
|
||||||
Type: sdktypes.TxReceived,
|
Type: sdktypes.TxReceived,
|
||||||
IsPending: false,
|
|
||||||
CreatedAt: time.Unix(1726054898, 0),
|
CreatedAt: time.Unix(1726054898, 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -81,7 +77,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 2000,
|
Amount: 2000,
|
||||||
Type: sdktypes.TxReceived,
|
Type: sdktypes.TxReceived,
|
||||||
IsPending: false,
|
|
||||||
CreatedAt: time.Unix(1726486359, 0),
|
CreatedAt: time.Unix(1726486359, 0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -96,7 +91,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 1000,
|
Amount: 1000,
|
||||||
Type: sdktypes.TxReceived,
|
Type: sdktypes.TxReceived,
|
||||||
IsPending: false,
|
|
||||||
CreatedAt: time.Unix(1726054898, 0),
|
CreatedAt: time.Unix(1726054898, 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -105,7 +99,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 2000,
|
Amount: 2000,
|
||||||
Type: sdktypes.TxReceived,
|
Type: sdktypes.TxReceived,
|
||||||
IsPending: false,
|
|
||||||
CreatedAt: time.Unix(1726486359, 0),
|
CreatedAt: time.Unix(1726486359, 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -114,7 +107,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Amount: 2100,
|
Amount: 2100,
|
||||||
Type: sdktypes.TxSent,
|
Type: sdktypes.TxSent,
|
||||||
IsPending: false,
|
|
||||||
CreatedAt: time.Unix(1726503865, 0),
|
CreatedAt: time.Unix(1726503865, 0),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -138,7 +130,6 @@ func TestVtxosToTxs(t *testing.T) {
|
|||||||
require.Equal(t, wantTx.RedeemTxid, gotTx.RedeemTxid)
|
require.Equal(t, wantTx.RedeemTxid, gotTx.RedeemTxid)
|
||||||
require.Equal(t, int(wantTx.Amount), int(gotTx.Amount))
|
require.Equal(t, int(wantTx.Amount), int(gotTx.Amount))
|
||||||
require.Equal(t, wantTx.Type, gotTx.Type)
|
require.Equal(t, wantTx.Type, gotTx.Type)
|
||||||
require.Equal(t, wantTx.IsPending, gotTx.IsPending)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -161,16 +152,12 @@ func loadFixtures(jsonStr string) (vtxos, map[string]struct{}, error) {
|
|||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Amount string `json:"amount"`
|
Amount string `json:"amount"`
|
||||||
} `json:"receiver"`
|
} `json:"receiver"`
|
||||||
Spent bool `json:"spent"`
|
Spent bool `json:"spent"`
|
||||||
PoolTxid string `json:"poolTxid"`
|
PoolTxid string `json:"poolTxid"`
|
||||||
SpentBy string `json:"spentBy"`
|
SpentBy string `json:"spentBy"`
|
||||||
ExpireAt string `json:"expireAt"`
|
ExpireAt string `json:"expireAt"`
|
||||||
Swept bool `json:"swept"`
|
Swept bool `json:"swept"`
|
||||||
Pending bool `json:"pending"`
|
RedeemTx string `json:"redeemTx"`
|
||||||
PendingData struct {
|
|
||||||
RedeemTx string `json:"redeemTx"`
|
|
||||||
UnconditionalForfeitTxs []string `json:"unconditionalForfeitTxs"`
|
|
||||||
} `json:"pendingData"`
|
|
||||||
} `json:"spendableVtxos"`
|
} `json:"spendableVtxos"`
|
||||||
SpentVtxos []struct {
|
SpentVtxos []struct {
|
||||||
Outpoint struct {
|
Outpoint struct {
|
||||||
@@ -181,16 +168,12 @@ func loadFixtures(jsonStr string) (vtxos, map[string]struct{}, error) {
|
|||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Amount string `json:"amount"`
|
Amount string `json:"amount"`
|
||||||
} `json:"receiver"`
|
} `json:"receiver"`
|
||||||
Spent bool `json:"spent"`
|
Spent bool `json:"spent"`
|
||||||
PoolTxid string `json:"poolTxid"`
|
PoolTxid string `json:"poolTxid"`
|
||||||
SpentBy string `json:"spentBy"`
|
SpentBy string `json:"spentBy"`
|
||||||
ExpireAt string `json:"expireAt"`
|
ExpireAt string `json:"expireAt"`
|
||||||
Swept bool `json:"swept"`
|
Swept bool `json:"swept"`
|
||||||
Pending bool `json:"pending"`
|
RedeemTx string `json:"redeemTx"`
|
||||||
PendingData struct {
|
|
||||||
RedeemTx string `json:"redeemTx"`
|
|
||||||
UnconditionalForfeitTxs []string `json:"unconditionalForfeitTxs"`
|
|
||||||
} `json:"pendingData"`
|
|
||||||
} `json:"spentVtxos"`
|
} `json:"spentVtxos"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,8 +199,7 @@ func loadFixtures(jsonStr string) (vtxos, map[string]struct{}, error) {
|
|||||||
Amount: amount,
|
Amount: amount,
|
||||||
RoundTxid: vtxo.PoolTxid,
|
RoundTxid: vtxo.PoolTxid,
|
||||||
ExpiresAt: &expireAt,
|
ExpiresAt: &expireAt,
|
||||||
RedeemTx: vtxo.PendingData.RedeemTx,
|
RedeemTx: vtxo.RedeemTx,
|
||||||
Pending: vtxo.Pending,
|
|
||||||
SpentBy: vtxo.SpentBy,
|
SpentBy: vtxo.SpentBy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,8 +222,7 @@ func loadFixtures(jsonStr string) (vtxos, map[string]struct{}, error) {
|
|||||||
Amount: amount,
|
Amount: amount,
|
||||||
RoundTxid: vtxo.PoolTxid,
|
RoundTxid: vtxo.PoolTxid,
|
||||||
ExpiresAt: &expireAt,
|
ExpiresAt: &expireAt,
|
||||||
RedeemTx: vtxo.PendingData.RedeemTx,
|
RedeemTx: vtxo.RedeemTx,
|
||||||
Pending: vtxo.Pending,
|
|
||||||
SpentBy: vtxo.SpentBy,
|
SpentBy: vtxo.SpentBy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,9 +282,7 @@ var (
|
|||||||
"poolTxid": "377fa2fbd27c82bdbc095478384c88b6c75432c0ef464189e49c965194446cdf",
|
"poolTxid": "377fa2fbd27c82bdbc095478384c88b6c75432c0ef464189e49c965194446cdf",
|
||||||
"spentBy": "",
|
"spentBy": "",
|
||||||
"expireAt": "1726054928",
|
"expireAt": "1726054928",
|
||||||
"swept": false,
|
"swept": false
|
||||||
"pending": false,
|
|
||||||
"pendingData": null
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spentVtxos": []
|
"spentVtxos": []
|
||||||
@@ -329,13 +308,7 @@ var (
|
|||||||
"spentBy": "",
|
"spentBy": "",
|
||||||
"expireAt": "1726054928",
|
"expireAt": "1726054928",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": false,
|
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"pendingData": {
|
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AVhNAAAAAAAAFgAUSU38/3Mzx5BdILG4oUO+JoHcoT8AAAAAAAEBKyBOAAAAAAAAIlEgp9TN/+j2H6vS/3LiebI632o7wSQO6ZA9BkZNsS/x9IVBFK8EgF7LdPQhXfncWS4YsyYwkWmodOuWIiwnAmx8mTOrsnQHxtDSP3zjaHmVR85ZxuPZN6gXHo4KmCgcipYgGEdAjH8Mg1Z3GdjGzp78Mg2xq1fop9KDfeji+xoyMgYS7q0Nl0AGOAaNzkDRW4cNcefll5jZC2i3nfygKdXsUsR+LEIVwVCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrApG1JPw/u15SlIXgMARt8mPk4hchPHlAZtmez8C3GobJFIKfbM/QraOxYRfgvdvWP4ycNc5EVsaujVEXfZF9OZkoXrSCvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq6zAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spentVtxos": [
|
"spentVtxos": [
|
||||||
@@ -353,8 +326,7 @@ var (
|
|||||||
"spentBy": "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
|
"spentBy": "94fa598302f17f00c8881e742ec0ce2f8c8d16f3d54fe6ba0fb7d13a493d84ad",
|
||||||
"expireAt": "1726054928",
|
"expireAt": "1726054928",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": false,
|
"redeemTx": ""
|
||||||
"pendingData": null
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`
|
}`
|
||||||
@@ -376,13 +348,7 @@ var (
|
|||||||
"spentBy": "",
|
"spentBy": "",
|
||||||
"expireAt": "1726054928",
|
"expireAt": "1726054928",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": true,
|
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"pendingData": {
|
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AVhNAAAAAAAAFgAUSU38/3Mzx5BdILG4oUO+JoHcoT8AAAAAAAEBKyBOAAAAAAAAIlEgp9TN/+j2H6vS/3LiebI632o7wSQO6ZA9BkZNsS/x9IVBFK8EgF7LdPQhXfncWS4YsyYwkWmodOuWIiwnAmx8mTOrsnQHxtDSP3zjaHmVR85ZxuPZN6gXHo4KmCgcipYgGEdAjH8Mg1Z3GdjGzp78Mg2xq1fop9KDfeji+xoyMgYS7q0Nl0AGOAaNzkDRW4cNcefll5jZC2i3nfygKdXsUsR+LEIVwVCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrApG1JPw/u15SlIXgMARt8mPk4hchPHlAZtmez8C3GobJFIKfbM/QraOxYRfgvdvWP4ycNc5EVsaujVEXfZF9OZkoXrSCvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq6zAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"outpoint": {
|
"outpoint": {
|
||||||
@@ -398,13 +364,7 @@ var (
|
|||||||
"spentBy": "",
|
"spentBy": "",
|
||||||
"expireAt": "1726486389",
|
"expireAt": "1726486389",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": true,
|
"redeemTx": "cHNidP8BAIkCAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AtAHAAAAAAAAIlEguuBh3KQUVZp+NHV2sixQ/mrsngCuLCGXzsgJPC1FzY7ANQ8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JAAAAAAABAStYPg8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JIgYCHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaMYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqQJsPdLYf7fAoXO82VoqwYHu1WevE4g6LxUGBPzfd96q5EEZkoW5qqg+v5dWJUEY467Q6qZLFHwziUaB3KEY8yEpCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wO5D2Mh3x0XNGxFCS67GNughkENFodpFeVpZjn76chI8RSAdVAV1eLK/AiUt2eOLwW9tSBv4QK5NE0AHrujAmeNxo60gnNco0P7x0R3r9t3yhgDS72zoZDWJhrZkVrfH0rM5TiWswCEWHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaM5AUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"pendingData": {
|
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AtAHAAAAAAAAIlEguuBh3KQUVZp+NHV2sixQ/mrsngCuLCGXzsgJPC1FzY7ANQ8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JAAAAAAABAStYPg8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JIgYCHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaMYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqQJsPdLYf7fAoXO82VoqwYHu1WevE4g6LxUGBPzfd96q5EEZkoW5qqg+v5dWJUEY467Q6qZLFHwziUaB3KEY8yEpCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wO5D2Mh3x0XNGxFCS67GNughkENFodpFeVpZjn76chI8RSAdVAV1eLK/AiUt2eOLwW9tSBv4QK5NE0AHrujAmeNxo60gnNco0P7x0R3r9t3yhgDS72zoZDWJhrZkVrfH0rM5TiWswCEWHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaM5AUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AZA9DwAAAAAAFgAU+9NJhjFhe8jX1hrXh3NvDyHZ1cYAAAAAAAEBK1g+DwAAAAAAIlEg/u5de2XiMtRxVVBT6xftYVebHYfqIIzOfuDJ7S/VjwlBFJzXKND+8dEd6/bd8oYA0u9s6GQ1iYa2ZFa3x9KzOU4lTNEVud/F3V+r2AgSlojS+tnDDy2Vn3iIQvvlChohtWpARJzBjlEkN/kTpyFEtpvP2Ui7ypevuxb9J/NUAwhYf8Pmnnj1l3WuKCSi4Fcp1O+lQjIiZlNpwY6J73q/V8Fe2kIVwFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrA7kPYyHfHRc0bEUJLrsY26CGQQ0Wh2kV5WlmOfvpyEjxFIB1UBXV4sr8CJS3Z44vBb21IG/hArk0TQAeu6MCZ43GjrSCc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJazAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spentVtxos": []
|
"spentVtxos": []
|
||||||
@@ -426,8 +386,7 @@ var (
|
|||||||
"spentBy": "",
|
"spentBy": "",
|
||||||
"expireAt": "1726503895",
|
"expireAt": "1726503895",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": false,
|
"redeemTx": ""
|
||||||
"pendingData": null
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spentVtxos": [
|
"spentVtxos": [
|
||||||
@@ -445,13 +404,7 @@ var (
|
|||||||
"spentBy": "d6684a5b9e6939dccdf07d1f0eaf7fdd7b31de4d123e63e400d23de739800d4e",
|
"spentBy": "d6684a5b9e6939dccdf07d1f0eaf7fdd7b31de4d123e63e400d23de739800d4e",
|
||||||
"expireAt": "1726054928",
|
"expireAt": "1726054928",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": true,
|
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"pendingData": {
|
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AVhNAAAAAAAAFgAUSU38/3Mzx5BdILG4oUO+JoHcoT8AAAAAAAEBKyBOAAAAAAAAIlEgp9TN/+j2H6vS/3LiebI632o7wSQO6ZA9BkZNsS/x9IVBFK8EgF7LdPQhXfncWS4YsyYwkWmodOuWIiwnAmx8mTOrsnQHxtDSP3zjaHmVR85ZxuPZN6gXHo4KmCgcipYgGEdAjH8Mg1Z3GdjGzp78Mg2xq1fop9KDfeji+xoyMgYS7q0Nl0AGOAaNzkDRW4cNcefll5jZC2i3nfygKdXsUsR+LEIVwVCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrApG1JPw/u15SlIXgMARt8mPk4hchPHlAZtmez8C3GobJFIKfbM/QraOxYRfgvdvWP4ycNc5EVsaujVEXfZF9OZkoXrSCvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq6zAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"outpoint": {
|
"outpoint": {
|
||||||
@@ -467,13 +420,7 @@ var (
|
|||||||
"spentBy": "d6684a5b9e6939dccdf07d1f0eaf7fdd7b31de4d123e63e400d23de739800d4e",
|
"spentBy": "d6684a5b9e6939dccdf07d1f0eaf7fdd7b31de4d123e63e400d23de739800d4e",
|
||||||
"expireAt": "1726486389",
|
"expireAt": "1726486389",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": true,
|
"redeemTx": "cHNidP8BAIkCAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AtAHAAAAAAAAIlEguuBh3KQUVZp+NHV2sixQ/mrsngCuLCGXzsgJPC1FzY7ANQ8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JAAAAAAABAStYPg8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JIgYCHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaMYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqQJsPdLYf7fAoXO82VoqwYHu1WevE4g6LxUGBPzfd96q5EEZkoW5qqg+v5dWJUEY467Q6qZLFHwziUaB3KEY8yEpCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wO5D2Mh3x0XNGxFCS67GNughkENFodpFeVpZjn76chI8RSAdVAV1eLK/AiUt2eOLwW9tSBv4QK5NE0AHrujAmeNxo60gnNco0P7x0R3r9t3yhgDS72zoZDWJhrZkVrfH0rM5TiWswCEWHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaM5AUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"pendingData": {
|
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AtAHAAAAAAAAIlEguuBh3KQUVZp+NHV2sixQ/mrsngCuLCGXzsgJPC1FzY7ANQ8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JAAAAAAABAStYPg8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JIgYCHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaMYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqQJsPdLYf7fAoXO82VoqwYHu1WevE4g6LxUGBPzfd96q5EEZkoW5qqg+v5dWJUEY467Q6qZLFHwziUaB3KEY8yEpCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wO5D2Mh3x0XNGxFCS67GNughkENFodpFeVpZjn76chI8RSAdVAV1eLK/AiUt2eOLwW9tSBv4QK5NE0AHrujAmeNxo60gnNco0P7x0R3r9t3yhgDS72zoZDWJhrZkVrfH0rM5TiWswCEWHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaM5AUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AZA9DwAAAAAAFgAU+9NJhjFhe8jX1hrXh3NvDyHZ1cYAAAAAAAEBK1g+DwAAAAAAIlEg/u5de2XiMtRxVVBT6xftYVebHYfqIIzOfuDJ7S/VjwlBFJzXKND+8dEd6/bd8oYA0u9s6GQ1iYa2ZFa3x9KzOU4lTNEVud/F3V+r2AgSlojS+tnDDy2Vn3iIQvvlChohtWpARJzBjlEkN/kTpyFEtpvP2Ui7ypevuxb9J/NUAwhYf8Pmnnj1l3WuKCSi4Fcp1O+lQjIiZlNpwY6J73q/V8Fe2kIVwFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrA7kPYyHfHRc0bEUJLrsY26CGQQ0Wh2kV5WlmOfvpyEjxFIB1UBXV4sr8CJS3Z44vBb21IG/hArk0TQAeu6MCZ43GjrSCc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJazAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`
|
}`
|
||||||
@@ -494,13 +441,7 @@ var (
|
|||||||
"spentBy": "",
|
"spentBy": "",
|
||||||
"expireAt": "1726503895",
|
"expireAt": "1726503895",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": false,
|
"redeemTx": "cHNidP8BAIkCAAAAAdOK9YzYw1ceJznqJxtRXGe0KeHj6CLcLtqLVwcbMCivAAAAAAD/////ArgLAAAAAAAAIlEgC39Vxhw3dIa4heHgFS6X4XwDl1mBggsKLVTBwF1h3qEgegEAAAAAACJRIMkktfIFxFNTtAmy3K0p+7JqVn2kcA0P6y2vJ1QX2zysAAAAAAABASughgEAAAAAACJRIMkktfIFxFNTtAmy3K0p+7JqVn2kcA0P6y2vJ1QX2zysIgYDjGeMfnNwCrU45iB3iRqiFdWTADaiJ968+w3ruFuq1F0YAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRTYEOuHJ0hyLBGzY8nSHpD2F1nby5/XQ5Sh2Je+cQ5Wsx0ZucLmB/LLspxMRN9JcJn3Q2KJRMhhg7415cCg1d0gQNSvgaBk/1WLYqQxCKxCfv8ViVJ7vjBxvNO5tc2FEDy27V9cIrfL1jPJoVrhgPZT0GwY7dkVZS7saIKI03CbipBCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wPKiQ0JM6aw2kcUByijEbOydM3gTIVCGN/69q+dmyxcqRSCMZ4x+c3AKtTjmIHeJGqIV1ZMANqIn3rz7Deu4W6rUXa0g2BDrhydIciwRs2PJ0h6Q9hdZ28uf10OUodiXvnEOVrOswCEWjGeMfnNwCrU45iB3iRqiFdWTADaiJ968+w3ruFuq1F05AR0ZucLmB/LLspxMRN9JcJn3Q2KJRMhhg7415cCg1d0gAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"pendingData": {
|
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAAdOK9YzYw1ceJznqJxtRXGe0KeHj6CLcLtqLVwcbMCivAAAAAAD/////ArgLAAAAAAAAIlEgC39Vxhw3dIa4heHgFS6X4XwDl1mBggsKLVTBwF1h3qEgegEAAAAAACJRIMkktfIFxFNTtAmy3K0p+7JqVn2kcA0P6y2vJ1QX2zysAAAAAAABASughgEAAAAAACJRIMkktfIFxFNTtAmy3K0p+7JqVn2kcA0P6y2vJ1QX2zysIgYDjGeMfnNwCrU45iB3iRqiFdWTADaiJ968+w3ruFuq1F0YAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRTYEOuHJ0hyLBGzY8nSHpD2F1nby5/XQ5Sh2Je+cQ5Wsx0ZucLmB/LLspxMRN9JcJn3Q2KJRMhhg7415cCg1d0gQNSvgaBk/1WLYqQxCKxCfv8ViVJ7vjBxvNO5tc2FEDy27V9cIrfL1jPJoVrhgPZT0GwY7dkVZS7saIKI03CbipBCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wPKiQ0JM6aw2kcUByijEbOydM3gTIVCGN/69q+dmyxcqRSCMZ4x+c3AKtTjmIHeJGqIV1ZMANqIn3rz7Deu4W6rUXa0g2BDrhydIciwRs2PJ0h6Q9hdZ28uf10OUodiXvnEOVrOswCEWjGeMfnNwCrU45iB3iRqiFdWTADaiJ968+w3ruFuq1F05AR0ZucLmB/LLspxMRN9JcJn3Q2KJRMhhg7415cCg1d0gAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAAdOK9YzYw1ceJznqJxtRXGe0KeHj6CLcLtqLVwcbMCivAAAAAAD/////AdiFAQAAAAAAFgAUlsBYsQa9BEiB8ZumuN4J50lbQIoAAAAAAAEBK6CGAQAAAAAAIlEgySS18gXEU1O0CbLcrSn7smpWfaRwDQ/rLa8nVBfbPKxBFNgQ64cnSHIsEbNjydIekPYXWdvLn9dDlKHYl75xDlazHRm5wuYH8suynExE30lwmfdDYolEyGGDvjXlwKDV3SBAZadgbU8gCDvq3XN0EeLIwGKGSAYHZRkGbAnr9ZjCHGKAQlfFNYS0af1Lz4j7Th2osVY8JJv7O736sC5NNQome0IVwFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrA8qJDQkzprDaRxQHKKMRs7J0zeBMhUIY3/r2r52bLFypFIIxnjH5zcAq1OOYgd4kaohXVkwA2oifevPsN67hbqtRdrSDYEOuHJ0hyLBGzY8nSHpD2F1nby5/XQ5Sh2Je+cQ5Ws6zAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"spentVtxos": [
|
"spentVtxos": [
|
||||||
@@ -518,13 +459,7 @@ var (
|
|||||||
"spentBy": "d6684a5b9e6939dccdf07d1f0eaf7fdd7b31de4d123e63e400d23de739800d4e",
|
"spentBy": "d6684a5b9e6939dccdf07d1f0eaf7fdd7b31de4d123e63e400d23de739800d4e",
|
||||||
"expireAt": "1726054928",
|
"expireAt": "1726054928",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": true,
|
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"pendingData": {
|
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AugDAAAAAAAAIlEgt2eR8LtqTP7yUcQtSydeGrRiHnVmHHnZwYjdC23G7MZwSQAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFAAAAAAABASsgTgAAAAAAACJRIKfUzf/o9h+r0v9y4nmyOt9qO8EkDumQPQZGTbEv8fSFIgYDp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShcYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq7J0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHQAFqkBLiRmP3AZ8MS77s1QIWZswMV3L72D9gN0f0MbD6XHkmzZeC1clF3uzxr+13wsF0vcFe29Zl3e2gAhMNGYVCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wKRtST8P7teUpSF4DAEbfJj5OIXITx5QGbZns/AtxqGyRSCn2zP0K2jsWEX4L3b1j+MnDXORFbGro1RF32RfTmZKF60grwSAXst09CFd+dxZLhizJjCRaah065YiLCcCbHyZM6uswCEWp9sz9Cto7FhF+C929Y/jJw1zkRWxq6NURd9kX05mShc5AbJ0B8bQ0j9842h5lUfOWcbj2TeoFx6OCpgoHIqWIBhHAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAAWwxXUjG5tidFA0LmUljX//jwW6xWaS6HKyRCw5StsxpAAAAAAD/////AVhNAAAAAAAAFgAUSU38/3Mzx5BdILG4oUO+JoHcoT8AAAAAAAEBKyBOAAAAAAAAIlEgp9TN/+j2H6vS/3LiebI632o7wSQO6ZA9BkZNsS/x9IVBFK8EgF7LdPQhXfncWS4YsyYwkWmodOuWIiwnAmx8mTOrsnQHxtDSP3zjaHmVR85ZxuPZN6gXHo4KmCgcipYgGEdAjH8Mg1Z3GdjGzp78Mg2xq1fop9KDfeji+xoyMgYS7q0Nl0AGOAaNzkDRW4cNcefll5jZC2i3nfygKdXsUsR+LEIVwVCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrApG1JPw/u15SlIXgMARt8mPk4hchPHlAZtmez8C3GobJFIKfbM/QraOxYRfgvdvWP4ycNc5EVsaujVEXfZF9OZkoXrSCvBIBey3T0IV353FkuGLMmMJFpqHTrliIsJwJsfJkzq6zAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"outpoint": {
|
"outpoint": {
|
||||||
@@ -541,12 +476,7 @@ var (
|
|||||||
"expireAt": "1726486389",
|
"expireAt": "1726486389",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": true,
|
"pending": true,
|
||||||
"pendingData": {
|
"redeemTx": "cHNidP8BAIkCAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AtAHAAAAAAAAIlEguuBh3KQUVZp+NHV2sixQ/mrsngCuLCGXzsgJPC1FzY7ANQ8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JAAAAAAABAStYPg8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JIgYCHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaMYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqQJsPdLYf7fAoXO82VoqwYHu1WevE4g6LxUGBPzfd96q5EEZkoW5qqg+v5dWJUEY467Q6qZLFHwziUaB3KEY8yEpCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wO5D2Mh3x0XNGxFCS67GNughkENFodpFeVpZjn76chI8RSAdVAV1eLK/AiUt2eOLwW9tSBv4QK5NE0AHrujAmeNxo60gnNco0P7x0R3r9t3yhgDS72zoZDWJhrZkVrfH0rM5TiWswCEWHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaM5AUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA="
|
||||||
"redeemTx": "cHNidP8BAIkCAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AtAHAAAAAAAAIlEguuBh3KQUVZp+NHV2sixQ/mrsngCuLCGXzsgJPC1FzY7ANQ8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JAAAAAAABAStYPg8AAAAAACJRIP7uXXtl4jLUcVVQU+sX7WFXmx2H6iCMzn7gye0v1Y8JIgYCHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaMYAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAQRSc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqQJsPdLYf7fAoXO82VoqwYHu1WevE4g6LxUGBPzfd96q5EEZkoW5qqg+v5dWJUEY467Q6qZLFHwziUaB3KEY8yEpCFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wO5D2Mh3x0XNGxFCS67GNughkENFodpFeVpZjn76chI8RSAdVAV1eLK/AiUt2eOLwW9tSBv4QK5NE0AHrujAmeNxo60gnNco0P7x0R3r9t3yhgDS72zoZDWJhrZkVrfH0rM5TiWswCEWHVQFdXiyvwIlLdnji8FvbUgb+ECuTRNAB67owJnjcaM5AUzRFbnfxd1fq9gIEpaI0vrZww8tlZ94iEL75QoaIbVqAAAAAFYAAIAAAACAAQAAgAAAAAAAAAAAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAAA=",
|
|
||||||
"unconditionalForfeitTxs": [
|
|
||||||
"cHNidP8BAFICAAAAARH6LJRGP/pFIkD/o5bBp8fXAhjl8yjfN7MhJsxdt5lrAQAAAAD/////AZA9DwAAAAAAFgAU+9NJhjFhe8jX1hrXh3NvDyHZ1cYAAAAAAAEBK1g+DwAAAAAAIlEg/u5de2XiMtRxVVBT6xftYVebHYfqIIzOfuDJ7S/VjwlBFJzXKND+8dEd6/bd8oYA0u9s6GQ1iYa2ZFa3x9KzOU4lTNEVud/F3V+r2AgSlojS+tnDDy2Vn3iIQvvlChohtWpARJzBjlEkN/kTpyFEtpvP2Ui7ypevuxb9J/NUAwhYf8Pmnnj1l3WuKCSi4Fcp1O+lQjIiZlNpwY6J73q/V8Fe2kIVwFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrA7kPYyHfHRc0bEUJLrsY26CGQQ0Wh2kV5WlmOfvpyEjxFIB1UBXV4sr8CJS3Z44vBb21IG/hArk0TQAeu6MCZ43GjrSCc1yjQ/vHRHev23fKGANLvbOhkNYmGtmRWt8fSszlOJazAARcgUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAAAA=="
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"outpoint": {
|
"outpoint": {
|
||||||
@@ -562,8 +492,7 @@ var (
|
|||||||
"spentBy": "23c3a885f0ea05f7bdf83f3bf7f8ac9dc3f791ad292f4e63a6f53fa5e4935ab0",
|
"spentBy": "23c3a885f0ea05f7bdf83f3bf7f8ac9dc3f791ad292f4e63a6f53fa5e4935ab0",
|
||||||
"expireAt": "1726503895",
|
"expireAt": "1726503895",
|
||||||
"swept": false,
|
"swept": false,
|
||||||
"pending": false,
|
"redeemTx": ""
|
||||||
"pendingData": null
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}`
|
}`
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/ark-network/ark/common"
|
"github.com/ark-network/ark/common"
|
||||||
"github.com/ark-network/ark/common/tree"
|
"github.com/ark-network/ark/common/tree"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/client"
|
"github.com/ark-network/ark/pkg/client-sdk/client"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/explorer"
|
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
|
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/redemption"
|
"github.com/ark-network/ark/pkg/client-sdk/redemption"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/types"
|
"github.com/ark-network/ark/pkg/client-sdk/types"
|
||||||
@@ -251,26 +250,6 @@ func (a *covenantArkClient) listenForBoardingUtxos(
|
|||||||
//are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
|
//are multiple boarding inputs + spent vtxo with change in spendable + received in the same round
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) ListVtxos(
|
|
||||||
ctx context.Context,
|
|
||||||
) (spendableVtxos, spentVtxos []client.Vtxo, err error) {
|
|
||||||
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, addr := range offchainAddrs {
|
|
||||||
spendable, spent, err := a.client.ListVtxos(ctx, addr.Address)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
spendableVtxos = append(spendableVtxos, spendable...)
|
|
||||||
spentVtxos = append(spentVtxos, spent...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *covenantArkClient) Balance(
|
func (a *covenantArkClient) Balance(
|
||||||
ctx context.Context, computeVtxoExpiration bool,
|
ctx context.Context, computeVtxoExpiration bool,
|
||||||
) (*Balance, error) {
|
) (*Balance, error) {
|
||||||
@@ -285,14 +264,13 @@ func (a *covenantArkClient) Balance(
|
|||||||
|
|
||||||
chRes := make(chan balanceRes, nbWorkers*len(offchainAddrs))
|
chRes := make(chan balanceRes, nbWorkers*len(offchainAddrs))
|
||||||
for i := range offchainAddrs {
|
for i := range offchainAddrs {
|
||||||
offchainAddr := offchainAddrs[i]
|
|
||||||
boardingAddr := boardingAddrs[i]
|
boardingAddr := boardingAddrs[i]
|
||||||
redeemAddr := redeemAddrs[i]
|
redeemAddr := redeemAddrs[i]
|
||||||
|
|
||||||
go func(addr string) {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
balance, amountByExpiration, err := a.getOffchainBalance(
|
balance, amountByExpiration, err := a.getOffchainBalance(
|
||||||
ctx, addr, computeVtxoExpiration,
|
ctx, computeVtxoExpiration,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chRes <- balanceRes{err: err}
|
chRes <- balanceRes{err: err}
|
||||||
@@ -303,7 +281,7 @@ func (a *covenantArkClient) Balance(
|
|||||||
offchainBalance: balance,
|
offchainBalance: balance,
|
||||||
offchainBalanceByExpiration: amountByExpiration,
|
offchainBalanceByExpiration: amountByExpiration,
|
||||||
}
|
}
|
||||||
}(offchainAddr.Address)
|
}()
|
||||||
|
|
||||||
getDelayedBalance := func(addr string) {
|
getDelayedBalance := func(addr string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
@@ -448,20 +426,11 @@ func (a *covenantArkClient) UnilateralRedeem(ctx context.Context) error {
|
|||||||
return fmt.Errorf("wallet is locked")
|
return fmt.Errorf("wallet is locked")
|
||||||
}
|
}
|
||||||
|
|
||||||
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
vtxos, err := a.getVtxos(ctx, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
vtxos := make([]client.Vtxo, 0)
|
|
||||||
for _, offchainAddr := range offchainAddrs {
|
|
||||||
fetchedVtxos, _, err := a.client.ListVtxos(ctx, offchainAddr.Address)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
vtxos = append(vtxos, fetchedVtxos...)
|
|
||||||
}
|
|
||||||
|
|
||||||
totalVtxosAmount := uint64(0)
|
totalVtxosAmount := uint64(0)
|
||||||
for _, vtxo := range vtxos {
|
for _, vtxo := range vtxos {
|
||||||
totalVtxosAmount += vtxo.Amount
|
totalVtxosAmount += vtxo.Amount
|
||||||
@@ -519,22 +488,13 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
|||||||
return "", fmt.Errorf("wallet is locked")
|
return "", fmt.Errorf("wallet is locked")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate liquid address
|
||||||
if _, err := address.ToOutputScript(addr); err != nil {
|
if _, err := address.ToOutputScript(addr); err != nil {
|
||||||
return "", fmt.Errorf("invalid onchain address")
|
return "", fmt.Errorf("invalid onchain address")
|
||||||
}
|
}
|
||||||
|
|
||||||
addrNet, err := address.NetworkForAddress(addr)
|
if isConf, err := address.IsConfidential(addr); err != nil || isConf {
|
||||||
if err != nil {
|
return "", fmt.Errorf("confidential onchain address not supported")
|
||||||
return "", fmt.Errorf("invalid onchain address: unknown network")
|
|
||||||
}
|
|
||||||
net := utils.ToElementsNetwork(a.Network)
|
|
||||||
if net.Name != addrNet.Name {
|
|
||||||
return "", fmt.Errorf("invalid onchain address: must be for %s network", net.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if isConf, _ := address.IsConfidential(addr); isConf {
|
|
||||||
info, _ := address.FromConfidential(addr)
|
|
||||||
addr = info.Address
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
||||||
@@ -550,22 +510,34 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
|||||||
}
|
}
|
||||||
|
|
||||||
vtxos := make([]client.DescriptorVtxo, 0)
|
vtxos := make([]client.DescriptorVtxo, 0)
|
||||||
for _, offchainAddr := range offchainAddrs {
|
spendableVtxos, err := a.getVtxos(ctx, false, nil)
|
||||||
spendableVtxos, err := a.getVtxos(ctx, offchainAddr.Address, withExpiryCoinselect)
|
if err != nil {
|
||||||
if err != nil {
|
return "", err
|
||||||
return "", err
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for _, vtxo := range spendableVtxos {
|
for _, offchainAddr := range offchainAddrs {
|
||||||
vtxos = append(vtxos, client.DescriptorVtxo{
|
for _, v := range spendableVtxos {
|
||||||
Vtxo: vtxo,
|
vtxoAddr, err := v.Address(a.AspPubkey, a.Network)
|
||||||
Descriptor: offchainAddr.Descriptor,
|
if err != nil {
|
||||||
})
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if vtxoAddr == offchainAddr.Address {
|
||||||
|
vtxos = append(vtxos, client.DescriptorVtxo{
|
||||||
|
Vtxo: v,
|
||||||
|
Descriptor: offchainAddr.Descriptor,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedCoins, changeAmount, err := utils.CoinSelect(
|
boardingUtxos, err := a.getClaimableBoardingUtxos(ctx, nil)
|
||||||
vtxos, amount, a.Dust, withExpiryCoinselect,
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedBoardingUtxos, selectedCoins, changeAmount, err := utils.CoinSelect(
|
||||||
|
boardingUtxos, vtxos, amount, a.Dust, withExpiryCoinselect,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -583,7 +555,7 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
inputs := make([]client.Input, 0, len(selectedCoins))
|
inputs := make([]client.Input, 0, len(selectedCoins)+len(selectedBoardingUtxos))
|
||||||
|
|
||||||
for _, coin := range selectedCoins {
|
for _, coin := range selectedCoins {
|
||||||
inputs = append(inputs, client.Input{
|
inputs = append(inputs, client.Input{
|
||||||
@@ -594,8 +566,17 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
|||||||
Descriptor: coin.Descriptor,
|
Descriptor: coin.Descriptor,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
for _, coin := range selectedBoardingUtxos {
|
||||||
|
inputs = append(inputs, client.Input{
|
||||||
|
Outpoint: client.Outpoint{
|
||||||
|
Txid: coin.Txid,
|
||||||
|
VOut: coin.VOut,
|
||||||
|
},
|
||||||
|
Descriptor: coin.Descriptor,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
paymentID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "") // ephemeralPublicKey is not required for covenant
|
paymentID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -604,9 +585,7 @@ func (a *covenantArkClient) CollaborativeRedeem(
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
poolTxID, err := a.handleRoundStream(
|
poolTxID, err := a.handleRoundStream(ctx, paymentID, selectedCoins, selectedBoardingUtxos, receivers)
|
||||||
ctx, paymentID, selectedCoins, nil, "", receivers,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -621,36 +600,10 @@ func (a *covenantArkClient) SendAsync(
|
|||||||
return "", fmt.Errorf("not implemented")
|
return "", fmt.Errorf("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) Claim(ctx context.Context) (string, error) {
|
func (a *covenantArkClient) Settle(
|
||||||
myselfOffchain, boardingAddr, err := a.wallet.NewAddress(ctx, false)
|
ctx context.Context,
|
||||||
if err != nil {
|
) (string, error) {
|
||||||
return "", err
|
return a.sendOffchain(ctx, false, nil)
|
||||||
}
|
|
||||||
|
|
||||||
boardingUtxos, err := a.getClaimableBoardingUtxos(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var pendingBalance uint64
|
|
||||||
for _, vtxo := range boardingUtxos {
|
|
||||||
pendingBalance += vtxo.Amount
|
|
||||||
}
|
|
||||||
if pendingBalance == 0 {
|
|
||||||
return "", fmt.Errorf("no funds to claim")
|
|
||||||
}
|
|
||||||
|
|
||||||
receiver := client.Output{
|
|
||||||
Address: myselfOffchain.Address,
|
|
||||||
Amount: pendingBalance,
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.selfTransferAllPendingPayments(
|
|
||||||
ctx,
|
|
||||||
boardingUtxos,
|
|
||||||
receiver,
|
|
||||||
boardingAddr.Descriptor,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) GetTransactionHistory(
|
func (a *covenantArkClient) GetTransactionHistory(
|
||||||
@@ -675,13 +628,13 @@ func (a *covenantArkClient) GetTransactionHistory(
|
|||||||
return vtxosToTxsCovenant(config.RoundLifetime, spendableVtxos, spentVtxos, boardingTxs)
|
return vtxosToTxsCovenant(config.RoundLifetime, spendableVtxos, spentVtxos, boardingTxs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) getAllBoardingUtxos(ctx context.Context) ([]explorer.Utxo, error) {
|
func (a *covenantArkClient) getAllBoardingUtxos(ctx context.Context) ([]types.Utxo, error) {
|
||||||
_, boardingAddrs, _, err := a.wallet.GetAddresses(ctx)
|
_, boardingAddrs, _, err := a.wallet.GetAddresses(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
utxos := []explorer.Utxo{}
|
utxos := make([]types.Utxo, 0)
|
||||||
for _, addr := range boardingAddrs {
|
for _, addr := range boardingAddrs {
|
||||||
txs, err := a.explorer.GetTxs(addr.Address)
|
txs, err := a.explorer.GetTxs(addr.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -694,11 +647,12 @@ func (a *covenantArkClient) getAllBoardingUtxos(ctx context.Context) ([]explorer
|
|||||||
if tx.Status.Confirmed {
|
if tx.Status.Confirmed {
|
||||||
createdAt = time.Unix(tx.Status.Blocktime, 0)
|
createdAt = time.Unix(tx.Status.Blocktime, 0)
|
||||||
}
|
}
|
||||||
utxos = append(utxos, explorer.Utxo{
|
utxos = append(utxos, types.Utxo{
|
||||||
Txid: tx.Txid,
|
Txid: tx.Txid,
|
||||||
Vout: uint32(i),
|
VOut: uint32(i),
|
||||||
Amount: vout.Amount,
|
Amount: vout.Amount,
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
|
Descriptor: addr.Descriptor,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -708,13 +662,13 @@ func (a *covenantArkClient) getAllBoardingUtxos(ctx context.Context) ([]explorer
|
|||||||
return utxos, nil
|
return utxos, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) getClaimableBoardingUtxos(ctx context.Context) ([]explorer.Utxo, error) {
|
func (a *covenantArkClient) getClaimableBoardingUtxos(ctx context.Context, opts *CoinSelectOptions) ([]types.Utxo, error) {
|
||||||
_, boardingAddrs, _, err := a.wallet.GetAddresses(ctx)
|
_, boardingAddrs, _, err := a.wallet.GetAddresses(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
claimable := make([]explorer.Utxo, 0)
|
claimable := make([]types.Utxo, 0)
|
||||||
|
|
||||||
for _, addr := range boardingAddrs {
|
for _, addr := range boardingAddrs {
|
||||||
boardingScript, err := tree.ParseVtxoScript(addr.Descriptor)
|
boardingScript, err := tree.ParseVtxoScript(addr.Descriptor)
|
||||||
@@ -738,8 +692,25 @@ func (a *covenantArkClient) getClaimableBoardingUtxos(ctx context.Context) ([]ex
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
for _, utxo := range boardingUtxos {
|
for _, utxo := range boardingUtxos {
|
||||||
u := utxo.ToUtxo(boardingTimeout)
|
if opts != nil && len(opts.OutpointsFilter) > 0 {
|
||||||
|
utxoOutpoint := client.Outpoint{
|
||||||
|
Txid: utxo.Txid,
|
||||||
|
VOut: utxo.Vout,
|
||||||
|
}
|
||||||
|
found := false
|
||||||
|
for _, outpoint := range opts.OutpointsFilter {
|
||||||
|
if outpoint.Equals(utxoOutpoint) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u := utxo.ToUtxo(boardingTimeout, addr.Descriptor)
|
||||||
if u.SpendableAt.Before(now) {
|
if u.SpendableAt.Before(now) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -906,84 +877,123 @@ func (a *covenantArkClient) sendOnchain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) sendOffchain(
|
func (a *covenantArkClient) sendOffchain(
|
||||||
ctx context.Context, withExpiryCoinselect bool, receivers []Receiver,
|
ctx context.Context,
|
||||||
|
withExpiryCoinselect bool, receivers []Receiver,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
if a.wallet.IsLocked() {
|
if a.wallet.IsLocked() {
|
||||||
return "", fmt.Errorf("wallet is locked")
|
return "", fmt.Errorf("wallet is locked")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectedAspPubKey := schnorr.SerializePubKey(a.AspPubkey)
|
||||||
|
outputs := make([]client.Output, 0)
|
||||||
|
sumOfReceivers := uint64(0)
|
||||||
|
|
||||||
|
// validate receivers and create outputs
|
||||||
|
for _, receiver := range receivers {
|
||||||
|
rcvAddr, err := common.DecodeAddress(receiver.To())
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("invalid receiver address: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rcvAspPubKey := schnorr.SerializePubKey(rcvAddr.Asp)
|
||||||
|
|
||||||
|
if !bytes.Equal(expectedAspPubKey, rcvAspPubKey) {
|
||||||
|
return "", fmt.Errorf("invalid receiver address '%s': expected ASP %s, got %s", receiver.To(), hex.EncodeToString(expectedAspPubKey), hex.EncodeToString(rcvAspPubKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
if receiver.Amount() < a.Dust {
|
||||||
|
return "", fmt.Errorf("invalid amount (%d), must be greater than dust %d", receiver.Amount(), a.Dust)
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs = append(outputs, client.Output{
|
||||||
|
Address: receiver.To(),
|
||||||
|
Amount: receiver.Amount(),
|
||||||
|
})
|
||||||
|
sumOfReceivers += receiver.Amount()
|
||||||
|
}
|
||||||
|
|
||||||
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
offchainAddrs, _, _, err := a.wallet.GetAddresses(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if len(offchainAddrs) <= 0 {
|
if len(offchainAddrs) <= 0 {
|
||||||
return "", fmt.Errorf("no funds detected")
|
return "", fmt.Errorf("no offchain addresses found")
|
||||||
}
|
|
||||||
|
|
||||||
expectedAspPubkey := schnorr.SerializePubKey(a.AspPubkey)
|
|
||||||
|
|
||||||
receiversOutput := make([]client.Output, 0)
|
|
||||||
sumOfReceivers := uint64(0)
|
|
||||||
|
|
||||||
for _, receiver := range receivers {
|
|
||||||
rcvAddr, err := common.DecodeAddress(receiver.To())
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("invalid receiver address: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
rcvAspPubkey := schnorr.SerializePubKey(rcvAddr.Asp)
|
|
||||||
|
|
||||||
if !bytes.Equal(rcvAspPubkey, expectedAspPubkey) {
|
|
||||||
return "", fmt.Errorf("invalid receiver address '%s': expected ASP %s, got %s", receiver.To(), hex.EncodeToString(expectedAspPubkey), hex.EncodeToString(rcvAspPubkey))
|
|
||||||
}
|
|
||||||
|
|
||||||
if receiver.Amount() < a.Dust {
|
|
||||||
return "", fmt.Errorf("invalid amount (%d), must be greater than dust %d", receiver.Amount(), a.Dust)
|
|
||||||
}
|
|
||||||
|
|
||||||
receiversOutput = append(receiversOutput, client.Output{
|
|
||||||
Address: receiver.To(),
|
|
||||||
Amount: receiver.Amount(),
|
|
||||||
})
|
|
||||||
sumOfReceivers += receiver.Amount()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vtxos := make([]client.DescriptorVtxo, 0)
|
vtxos := make([]client.DescriptorVtxo, 0)
|
||||||
for _, offchainAddr := range offchainAddrs {
|
|
||||||
spendableVtxos, err := a.getVtxos(ctx, offchainAddr.Address, withExpiryCoinselect)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, vtxo := range spendableVtxos {
|
spendableVtxos, err := a.getVtxos(ctx, withExpiryCoinselect, nil)
|
||||||
vtxos = append(vtxos, client.DescriptorVtxo{
|
if err != nil {
|
||||||
Vtxo: vtxo,
|
return "", err
|
||||||
Descriptor: offchainAddr.Descriptor,
|
}
|
||||||
})
|
|
||||||
|
for _, offchainAddr := range offchainAddrs {
|
||||||
|
for _, v := range spendableVtxos {
|
||||||
|
vtxoAddr, err := v.Address(a.AspPubkey, a.Network)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if vtxoAddr == offchainAddr.Address {
|
||||||
|
vtxos = append(vtxos, client.DescriptorVtxo{
|
||||||
|
Vtxo: v,
|
||||||
|
Descriptor: offchainAddr.Descriptor,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedCoins, changeAmount, err := utils.CoinSelect(
|
boardingUtxos, err := a.getClaimableBoardingUtxos(ctx, nil)
|
||||||
vtxos, sumOfReceivers, a.Dust, withExpiryCoinselect,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var selectedBoardingCoins []types.Utxo
|
||||||
|
var selectedCoins []client.DescriptorVtxo
|
||||||
|
var changeAmount uint64
|
||||||
|
|
||||||
|
// if no receivers, self send all selected coins
|
||||||
|
if len(outputs) <= 0 {
|
||||||
|
selectedBoardingCoins = boardingUtxos
|
||||||
|
selectedCoins = vtxos
|
||||||
|
|
||||||
|
amount := uint64(0)
|
||||||
|
for _, utxo := range boardingUtxos {
|
||||||
|
amount += utxo.Amount
|
||||||
|
}
|
||||||
|
for _, utxo := range vtxos {
|
||||||
|
amount += utxo.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
outputs = append(outputs, client.Output{
|
||||||
|
Address: offchainAddrs[0].Address,
|
||||||
|
Amount: amount,
|
||||||
|
})
|
||||||
|
|
||||||
|
changeAmount = 0
|
||||||
|
} else {
|
||||||
|
selectedBoardingCoins, selectedCoins, changeAmount, err = utils.CoinSelect(
|
||||||
|
boardingUtxos, vtxos, sumOfReceivers, a.Dust, withExpiryCoinselect,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if changeAmount > 0 {
|
if changeAmount > 0 {
|
||||||
offchainAddr, _, err := a.wallet.NewAddress(ctx, true)
|
offchainAddr, _, err := a.wallet.NewAddress(ctx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
changeReceiver := client.Output{
|
outputs = append(outputs, client.Output{
|
||||||
Address: offchainAddr.Address,
|
Address: offchainAddr.Address,
|
||||||
Amount: changeAmount,
|
Amount: changeAmount,
|
||||||
}
|
})
|
||||||
receiversOutput = append(receiversOutput, changeReceiver)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inputs := make([]client.Input, 0, len(selectedCoins))
|
inputs := make([]client.Input, 0, len(selectedCoins)+len(selectedBoardingCoins))
|
||||||
|
|
||||||
for _, coin := range selectedCoins {
|
for _, coin := range selectedCoins {
|
||||||
inputs = append(inputs, client.Input{
|
inputs = append(inputs, client.Input{
|
||||||
Outpoint: client.Outpoint{
|
Outpoint: client.Outpoint{
|
||||||
@@ -993,16 +1003,23 @@ func (a *covenantArkClient) sendOffchain(
|
|||||||
Descriptor: coin.Descriptor,
|
Descriptor: coin.Descriptor,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
for _, coin := range selectedBoardingCoins {
|
||||||
|
inputs = append(inputs, client.Input{
|
||||||
|
Outpoint: client.Outpoint{
|
||||||
|
Txid: coin.Txid,
|
||||||
|
VOut: coin.VOut,
|
||||||
|
},
|
||||||
|
Descriptor: coin.Descriptor,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
paymentID, err := a.client.RegisterInputsForNextRound(
|
paymentID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "")
|
||||||
ctx, inputs, "", // ephemeralPublicKey is not required for covenant
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.client.RegisterOutputsForNextRound(
|
if err := a.client.RegisterOutputsForNextRound(
|
||||||
ctx, paymentID, receiversOutput,
|
ctx, paymentID, outputs,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -1010,7 +1027,7 @@ func (a *covenantArkClient) sendOffchain(
|
|||||||
log.Infof("payment registered with id: %s", paymentID)
|
log.Infof("payment registered with id: %s", paymentID)
|
||||||
|
|
||||||
poolTxID, err := a.handleRoundStream(
|
poolTxID, err := a.handleRoundStream(
|
||||||
ctx, paymentID, selectedCoins, nil, "", receiversOutput,
|
ctx, paymentID, selectedCoins, boardingUtxos, outputs,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -1023,7 +1040,7 @@ func (a *covenantArkClient) sendOffchain(
|
|||||||
func (a *covenantArkClient) addInputs(
|
func (a *covenantArkClient) addInputs(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
updater *psetv2.Updater,
|
updater *psetv2.Updater,
|
||||||
utxos []explorer.Utxo,
|
utxos []types.Utxo,
|
||||||
) error {
|
) error {
|
||||||
// TODO works only with single-key wallet
|
// TODO works only with single-key wallet
|
||||||
offchain, _, err := a.wallet.NewAddress(ctx, false)
|
offchain, _, err := a.wallet.NewAddress(ctx, false)
|
||||||
@@ -1055,7 +1072,7 @@ func (a *covenantArkClient) addInputs(
|
|||||||
if err := updater.AddInputs([]psetv2.InputArgs{
|
if err := updater.AddInputs([]psetv2.InputArgs{
|
||||||
{
|
{
|
||||||
Txid: utxo.Txid,
|
Txid: utxo.Txid,
|
||||||
TxIndex: utxo.Vout,
|
TxIndex: utxo.VOut,
|
||||||
Sequence: sequence,
|
Sequence: sequence,
|
||||||
},
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@@ -1113,8 +1130,7 @@ func (a *covenantArkClient) handleRoundStream(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
paymentID string,
|
paymentID string,
|
||||||
vtxosToSign []client.DescriptorVtxo,
|
vtxosToSign []client.DescriptorVtxo,
|
||||||
boardingUtxos []explorer.Utxo,
|
boardingUtxos []types.Utxo,
|
||||||
boardingDescriptor string,
|
|
||||||
receivers []client.Output,
|
receivers []client.Output,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
eventsCh, close, err := a.client.GetEventStream(ctx, paymentID)
|
eventsCh, close, err := a.client.GetEventStream(ctx, paymentID)
|
||||||
@@ -1151,7 +1167,7 @@ func (a *covenantArkClient) handleRoundStream(
|
|||||||
log.Info("a round finalization started")
|
log.Info("a round finalization started")
|
||||||
|
|
||||||
signedForfeitTxs, signedRoundTx, err := a.handleRoundFinalization(
|
signedForfeitTxs, signedRoundTx, err := a.handleRoundFinalization(
|
||||||
ctx, event.(client.RoundFinalizationEvent), vtxosToSign, boardingUtxos, boardingDescriptor, receivers,
|
ctx, event.(client.RoundFinalizationEvent), vtxosToSign, boardingUtxos, receivers,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -1178,8 +1194,7 @@ func (a *covenantArkClient) handleRoundFinalization(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
event client.RoundFinalizationEvent,
|
event client.RoundFinalizationEvent,
|
||||||
vtxos []client.DescriptorVtxo,
|
vtxos []client.DescriptorVtxo,
|
||||||
boardingUtxos []explorer.Utxo,
|
boardingUtxos []types.Utxo,
|
||||||
boardingDescriptor string,
|
|
||||||
receivers []client.Output,
|
receivers []client.Output,
|
||||||
) (signedForfeits []string, signedRoundTx string, err error) {
|
) (signedForfeits []string, signedRoundTx string, err error) {
|
||||||
if err = a.validateCongestionTree(event, receivers); err != nil {
|
if err = a.validateCongestionTree(event, receivers); err != nil {
|
||||||
@@ -1193,13 +1208,23 @@ func (a *covenantArkClient) handleRoundFinalization(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(boardingUtxos) > 0 {
|
// if no boarding utxos inputs, we don't need to sign the round transaction
|
||||||
boardingVtxoScript, err := tree.ParseVtxoScript(boardingDescriptor)
|
if len(boardingUtxos) <= 0 {
|
||||||
if err != nil {
|
return
|
||||||
return nil, "", err
|
}
|
||||||
}
|
|
||||||
|
|
||||||
roundPtx, err := psetv2.NewPsetFromBase64(event.Tx)
|
roundPtx, err := psetv2.NewPsetFromBase64(event.Tx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
updater, err := psetv2.NewUpdater(roundPtx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, boardingUtxo := range boardingUtxos {
|
||||||
|
boardingVtxoScript, err := tree.ParseVtxoScript(boardingUtxo.Descriptor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
@@ -1213,7 +1238,7 @@ func (a *covenantArkClient) handleRoundFinalization(
|
|||||||
AspPubkey: a.AspPubkey,
|
AspPubkey: a.AspPubkey,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, "", fmt.Errorf("unsupported boarding descriptor: %s", boardingDescriptor)
|
return nil, "", fmt.Errorf("unsupported boarding descriptor: %s", boardingUtxo.Descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
forfeitLeaf, err := forfeitClosure.Leaf()
|
forfeitLeaf, err := forfeitClosure.Leaf()
|
||||||
@@ -1241,31 +1266,25 @@ func (a *covenantArkClient) handleRoundFinalization(
|
|||||||
ControlBlock: *ctrlBlock,
|
ControlBlock: *ctrlBlock,
|
||||||
}
|
}
|
||||||
|
|
||||||
updater, err := psetv2.NewUpdater(roundPtx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, input := range updater.Pset.Inputs {
|
for i, input := range updater.Pset.Inputs {
|
||||||
for _, boardingUtxo := range boardingUtxos {
|
if chainhash.Hash(input.PreviousTxid).String() == boardingUtxo.Txid && boardingUtxo.VOut == input.PreviousTxIndex {
|
||||||
if chainhash.Hash(input.PreviousTxid).String() == boardingUtxo.Txid && boardingUtxo.Vout == input.PreviousTxIndex {
|
if err := updater.AddInTapLeafScript(i, tapscript); err != nil {
|
||||||
if err := updater.AddInTapLeafScript(i, tapscript); err != nil {
|
return nil, "", err
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b64, err := updater.Pset.ToBase64()
|
}
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
signedRoundTx, err = a.wallet.SignTransaction(ctx, a.explorer, b64)
|
b64, err := updater.Pset.ToBase64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signedRoundTx, err = a.wallet.SignTransaction(ctx, a.explorer, b64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return signedForfeits, signedRoundTx, nil
|
return signedForfeits, signedRoundTx, nil
|
||||||
@@ -1518,8 +1537,8 @@ func (a *covenantArkClient) createAndSignForfeits(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) coinSelectOnchain(
|
func (a *covenantArkClient) coinSelectOnchain(
|
||||||
ctx context.Context, targetAmount uint64, exclude []explorer.Utxo,
|
ctx context.Context, targetAmount uint64, exclude []types.Utxo,
|
||||||
) ([]explorer.Utxo, uint64, error) {
|
) ([]types.Utxo, uint64, error) {
|
||||||
_, boardingAddrs, redemptionAddrs, err := a.wallet.GetAddresses(ctx)
|
_, boardingAddrs, redemptionAddrs, err := a.wallet.GetAddresses(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -1527,7 +1546,7 @@ func (a *covenantArkClient) coinSelectOnchain(
|
|||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
fetchedUtxos := make([]explorer.Utxo, 0)
|
fetchedUtxos := make([]types.Utxo, 0)
|
||||||
for _, addr := range boardingAddrs {
|
for _, addr := range boardingAddrs {
|
||||||
boardingDescriptor := addr.Descriptor
|
boardingDescriptor := addr.Descriptor
|
||||||
|
|
||||||
@@ -1550,14 +1569,14 @@ func (a *covenantArkClient) coinSelectOnchain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, utxo := range utxos {
|
for _, utxo := range utxos {
|
||||||
u := utxo.ToUtxo(boardingTimeout)
|
u := utxo.ToUtxo(boardingTimeout, addr.Descriptor)
|
||||||
if u.SpendableAt.Before(now) {
|
if u.SpendableAt.Before(now) {
|
||||||
fetchedUtxos = append(fetchedUtxos, u)
|
fetchedUtxos = append(fetchedUtxos, u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selected := make([]explorer.Utxo, 0)
|
selected := make([]types.Utxo, 0)
|
||||||
selectedAmount := uint64(0)
|
selectedAmount := uint64(0)
|
||||||
for _, utxo := range fetchedUtxos {
|
for _, utxo := range fetchedUtxos {
|
||||||
if selectedAmount >= targetAmount {
|
if selectedAmount >= targetAmount {
|
||||||
@@ -1565,7 +1584,7 @@ func (a *covenantArkClient) coinSelectOnchain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, excluded := range exclude {
|
for _, excluded := range exclude {
|
||||||
if utxo.Txid == excluded.Txid && utxo.Vout == excluded.Vout {
|
if utxo.Txid == excluded.Txid && utxo.VOut == excluded.VOut {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1578,7 +1597,7 @@ func (a *covenantArkClient) coinSelectOnchain(
|
|||||||
return selected, selectedAmount - targetAmount, nil
|
return selected, selectedAmount - targetAmount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchedUtxos = make([]explorer.Utxo, 0)
|
fetchedUtxos = make([]types.Utxo, 0)
|
||||||
for _, addr := range redemptionAddrs {
|
for _, addr := range redemptionAddrs {
|
||||||
utxos, err := a.explorer.GetUtxos(addr.Address)
|
utxos, err := a.explorer.GetUtxos(addr.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1586,7 +1605,7 @@ func (a *covenantArkClient) coinSelectOnchain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, utxo := range utxos {
|
for _, utxo := range utxos {
|
||||||
u := utxo.ToUtxo(uint(a.UnilateralExitDelay))
|
u := utxo.ToUtxo(uint(a.UnilateralExitDelay), addr.Descriptor)
|
||||||
if u.SpendableAt.Before(now) {
|
if u.SpendableAt.Before(now) {
|
||||||
fetchedUtxos = append(fetchedUtxos, u)
|
fetchedUtxos = append(fetchedUtxos, u)
|
||||||
}
|
}
|
||||||
@@ -1599,7 +1618,7 @@ func (a *covenantArkClient) coinSelectOnchain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, excluded := range exclude {
|
for _, excluded := range exclude {
|
||||||
if utxo.Txid == excluded.Txid && utxo.Vout == excluded.Vout {
|
if utxo.Txid == excluded.Txid && utxo.VOut == excluded.VOut {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1648,11 +1667,11 @@ func (a *covenantArkClient) getRedeemBranches(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) getOffchainBalance(
|
func (a *covenantArkClient) getOffchainBalance(
|
||||||
ctx context.Context, addr string, computeVtxoExpiration bool,
|
ctx context.Context, computeVtxoExpiration bool,
|
||||||
) (uint64, map[int64]uint64, error) {
|
) (uint64, map[int64]uint64, error) {
|
||||||
amountByExpiration := make(map[int64]uint64, 0)
|
amountByExpiration := make(map[int64]uint64, 0)
|
||||||
|
|
||||||
vtxos, err := a.getVtxos(ctx, addr, computeVtxoExpiration)
|
vtxos, err := a.getVtxos(ctx, computeVtxoExpiration, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
@@ -1675,18 +1694,24 @@ func (a *covenantArkClient) getOffchainBalance(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) getVtxos(
|
func (a *covenantArkClient) getVtxos(
|
||||||
ctx context.Context, addr string, computeVtxoExpiration bool,
|
ctx context.Context,
|
||||||
|
withExpiryCoinselect bool, opts *CoinSelectOptions,
|
||||||
) ([]client.Vtxo, error) {
|
) ([]client.Vtxo, error) {
|
||||||
vtxos, _, err := a.client.ListVtxos(ctx, addr)
|
spendableVtxos, _, err := a.ListVtxos(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !computeVtxoExpiration {
|
if opts != nil && len(opts.OutpointsFilter) > 0 {
|
||||||
return vtxos, nil
|
spendableVtxos = filterByOutpoints(spendableVtxos, opts.OutpointsFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
redeemBranches, err := a.getRedeemBranches(ctx, vtxos)
|
if opts == nil || !opts.WithExpirySorting {
|
||||||
|
return spendableVtxos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if sorting by expiry is required, we need to get the expiration date of each vtxo
|
||||||
|
redeemBranches, err := a.getRedeemBranches(ctx, spendableVtxos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -1697,75 +1722,24 @@ func (a *covenantArkClient) getVtxos(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, vtxo := range vtxos {
|
for i, vtxo := range spendableVtxos {
|
||||||
if vtxo.Txid == vtxoTxid {
|
if vtxo.Txid == vtxoTxid {
|
||||||
vtxos[i].ExpiresAt = expiration
|
spendableVtxos[i].ExpiresAt = expiration
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vtxos, nil
|
return spendableVtxos, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (a *covenantArkClient) selfTransferAllPendingPayments(
|
|
||||||
ctx context.Context, boardingUtxos []explorer.Utxo, myself client.Output, boardingDescriptor string,
|
|
||||||
) (string, error) {
|
|
||||||
inputs := make([]client.Input, 0, len(boardingUtxos))
|
|
||||||
|
|
||||||
for _, utxo := range boardingUtxos {
|
|
||||||
inputs = append(inputs, client.Input{
|
|
||||||
Outpoint: client.Outpoint{
|
|
||||||
Txid: utxo.Txid,
|
|
||||||
VOut: utxo.Vout,
|
|
||||||
},
|
|
||||||
Descriptor: boardingDescriptor,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
outputs := []client.Output{myself}
|
|
||||||
|
|
||||||
paymentID, err := a.client.RegisterInputsForNextRound(ctx, inputs, "") // ephemeralPublicKey is not required for covenant
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := a.client.RegisterOutputsForNextRound(ctx, paymentID, outputs); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
roundTxid, err := a.handleRoundStream(
|
|
||||||
ctx, paymentID, make([]client.DescriptorVtxo, 0), boardingUtxos, boardingDescriptor, outputs,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return roundTxid, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *covenantArkClient) getBoardingTxs(ctx context.Context) (transactions []types.Transaction) {
|
func (a *covenantArkClient) getBoardingTxs(ctx context.Context) (transactions []types.Transaction) {
|
||||||
utxos, err := a.getClaimableBoardingUtxos(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
isPending := make(map[string]bool)
|
|
||||||
for _, u := range utxos {
|
|
||||||
isPending[u.Txid] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
allUtxos, err := a.getAllBoardingUtxos(ctx)
|
allUtxos, err := a.getAllBoardingUtxos(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, u := range allUtxos {
|
for _, u := range allUtxos {
|
||||||
pending := false
|
|
||||||
if isPending[u.Txid] {
|
|
||||||
pending = true
|
|
||||||
}
|
|
||||||
|
|
||||||
transactions = append(transactions, types.Transaction{
|
transactions = append(transactions, types.Transaction{
|
||||||
TransactionKey: types.TransactionKey{
|
TransactionKey: types.TransactionKey{
|
||||||
BoardingTxid: u.Txid,
|
BoardingTxid: u.Txid,
|
||||||
@@ -1773,7 +1747,6 @@ func (a *covenantArkClient) getBoardingTxs(ctx context.Context) (transactions []
|
|||||||
Amount: u.Amount,
|
Amount: u.Amount,
|
||||||
Type: types.TxReceived,
|
Type: types.TxReceived,
|
||||||
CreatedAt: u.CreatedAt,
|
CreatedAt: u.CreatedAt,
|
||||||
IsPending: pending,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -1796,9 +1769,7 @@ func vtxosToTxsCovenant(
|
|||||||
for _, v := range append(spendable, spent...) {
|
for _, v := range append(spendable, spent...) {
|
||||||
// get vtxo amount
|
// get vtxo amount
|
||||||
amount := int(v.Amount)
|
amount := int(v.Amount)
|
||||||
if !v.Pending {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// find other spent vtxos that spent this one
|
// find other spent vtxos that spent this one
|
||||||
relatedVtxos := findVtxosBySpentBy(spent, v.Txid)
|
relatedVtxos := findVtxosBySpentBy(spent, v.Txid)
|
||||||
for _, r := range relatedVtxos {
|
for _, r := range relatedVtxos {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -55,8 +55,8 @@ func main() {
|
|||||||
onboardAmount := uint64(1_0000_0000) // 1 BTC
|
onboardAmount := uint64(1_0000_0000) // 1 BTC
|
||||||
log.Infof("alice is onboarding with %d sats offchain...", onboardAmount)
|
log.Infof("alice is onboarding with %d sats offchain...", onboardAmount)
|
||||||
|
|
||||||
log.Infof("alice claiming onboarding funds...")
|
log.Infof("alice settled the onboard funds...")
|
||||||
txid, err := aliceArkClient.Claim(ctx)
|
txid, err := aliceArkClient.Settle(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,13 +84,13 @@ func main() {
|
|||||||
log.Infof("alice onchain balance: %d", aliceBalance.OnchainBalance.SpendableAmount)
|
log.Infof("alice onchain balance: %d", aliceBalance.OnchainBalance.SpendableAmount)
|
||||||
log.Infof("alice offchain balance: %d", aliceBalance.OffchainBalance.Total)
|
log.Infof("alice offchain balance: %d", aliceBalance.OffchainBalance.Total)
|
||||||
|
|
||||||
log.Infof("alice claiming onboarding funds...")
|
log.Infof("alice is settling the onboard funds...")
|
||||||
txid, err := aliceArkClient.Claim(ctx)
|
txid, err := aliceArkClient.Settle(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("alice claimed onboarding funds in round %s", txid)
|
log.Infof("alice settled the onboard funds in round %s", txid)
|
||||||
|
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
log.Info("bob is setting up his ark wallet...")
|
log.Info("bob is setting up his ark wallet...")
|
||||||
@@ -128,7 +128,7 @@ func main() {
|
|||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
log.Infof("alice is sending %d sats to bob offchain...", amount)
|
log.Infof("alice is sending %d sats to bob offchain...", amount)
|
||||||
|
|
||||||
if _, err = aliceArkClient.SendAsync(ctx, false, receivers); err != nil {
|
if _, err = aliceArkClient.SendOffChain(ctx, false, receivers); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,13 +158,13 @@ func main() {
|
|||||||
log.Infof("bob offchain balance: %d", bobBalance.OffchainBalance.Total)
|
log.Infof("bob offchain balance: %d", bobBalance.OffchainBalance.Total)
|
||||||
|
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
log.Info("bob is claiming the incoming payment...")
|
log.Info("bob is settling the received funds...")
|
||||||
roundTxid, err := bobArkClient.Claim(ctx)
|
roundTxid, err := bobArkClient.Settle(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("bob claimed the incoming payment in round %s", roundTxid)
|
log.Infof("bob settled the received funds in round %s", roundTxid)
|
||||||
|
|
||||||
time.Sleep(500 * time.Second)
|
time.Sleep(500 * time.Second)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,19 +90,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function claimVtxos() {
|
async function settleVtxos() {
|
||||||
const password = document.getElementById("c_password").value;
|
const password = document.getElementById("c_password").value;
|
||||||
if (!password) {
|
if (!password) {
|
||||||
logMessage("Claim error: password is required");
|
logMessage("Settle error: password is required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await unlock(password);
|
await unlock(password);
|
||||||
const txID = await claim();
|
const txID = await settle();
|
||||||
logMessage("Claimed money with tx ID: " + txID);
|
logMessage("Settled money with tx ID: " + txID);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logMessage("Claim error: " + err.message);
|
logMessage("Settle error: " + err.message);
|
||||||
} finally {
|
} finally {
|
||||||
await lock(password);
|
await lock(password);
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@
|
|||||||
<input type="password" id="s_password" placeholder="password">
|
<input type="password" id="s_password" placeholder="password">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button onclick="claimVtxos()">Claim</button>
|
<button onclick="settleVtxos()">Settle</button>
|
||||||
<input type="password" id="c_password" placeholder="password">
|
<input type="password" id="c_password" placeholder="password">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ark-network/ark/common"
|
"github.com/ark-network/ark/common"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
|
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
|
||||||
|
"github.com/ark-network/ark/pkg/client-sdk/types"
|
||||||
"github.com/btcsuite/btcd/btcutil/psbt"
|
"github.com/btcsuite/btcd/btcutil/psbt"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/vulpemventures/go-elements/psetv2"
|
"github.com/vulpemventures/go-elements/psetv2"
|
||||||
@@ -24,39 +25,6 @@ const (
|
|||||||
LiquidExplorer = "liquid"
|
LiquidExplorer = "liquid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Utxo struct {
|
|
||||||
Txid string
|
|
||||||
Vout uint32
|
|
||||||
Amount uint64
|
|
||||||
Asset string // liquid only
|
|
||||||
Delay uint
|
|
||||||
SpendableAt time.Time
|
|
||||||
CreatedAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *Utxo) Sequence() (uint32, error) {
|
|
||||||
return common.BIP68Sequence(u.Delay)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newUtxo(explorerUtxo ExplorerUtxo, delay uint) Utxo {
|
|
||||||
utxoTime := explorerUtxo.Status.Blocktime
|
|
||||||
createdAt := time.Unix(utxoTime, 0)
|
|
||||||
if utxoTime == 0 {
|
|
||||||
createdAt = time.Time{}
|
|
||||||
utxoTime = time.Now().Unix()
|
|
||||||
}
|
|
||||||
|
|
||||||
return Utxo{
|
|
||||||
Txid: explorerUtxo.Txid,
|
|
||||||
Vout: explorerUtxo.Vout,
|
|
||||||
Amount: explorerUtxo.Amount,
|
|
||||||
Asset: explorerUtxo.Asset,
|
|
||||||
Delay: delay,
|
|
||||||
SpendableAt: time.Unix(utxoTime, 0).Add(time.Duration(delay) * time.Second),
|
|
||||||
CreatedAt: createdAt,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ExplorerTx struct {
|
type ExplorerTx struct {
|
||||||
Txid string `json:"txid"`
|
Txid string `json:"txid"`
|
||||||
Vout []struct {
|
Vout []struct {
|
||||||
@@ -85,8 +53,8 @@ type SpentStatus struct {
|
|||||||
SpentBy string `json:"txid,omitempty"`
|
SpentBy string `json:"txid,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e ExplorerUtxo) ToUtxo(delay uint) Utxo {
|
func (e ExplorerUtxo) ToUtxo(delay uint, descriptor string) types.Utxo {
|
||||||
return newUtxo(e, delay)
|
return newUtxo(e, delay, descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Explorer interface {
|
type Explorer interface {
|
||||||
@@ -446,3 +414,23 @@ func parseBitcoinTx(txStr string) (string, string, error) {
|
|||||||
|
|
||||||
return txhex, txid, nil
|
return txhex, txid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newUtxo(explorerUtxo ExplorerUtxo, delay uint, descriptor string) types.Utxo {
|
||||||
|
utxoTime := explorerUtxo.Status.Blocktime
|
||||||
|
createdAt := time.Unix(utxoTime, 0)
|
||||||
|
if utxoTime == 0 {
|
||||||
|
createdAt = time.Time{}
|
||||||
|
utxoTime = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.Utxo{
|
||||||
|
Txid: explorerUtxo.Txid,
|
||||||
|
VOut: explorerUtxo.Vout,
|
||||||
|
Amount: explorerUtxo.Amount,
|
||||||
|
Asset: explorerUtxo.Asset,
|
||||||
|
Delay: delay,
|
||||||
|
SpendableAt: time.Unix(utxoTime, 0).Add(time.Duration(delay) * time.Second),
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
Descriptor: descriptor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ark-network/ark/common"
|
"github.com/ark-network/ark/common"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/client"
|
"github.com/ark-network/ark/pkg/client-sdk/client"
|
||||||
|
"github.com/ark-network/ark/pkg/client-sdk/types"
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
@@ -23,10 +24,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func CoinSelect(
|
func CoinSelect(
|
||||||
vtxos []client.DescriptorVtxo, amount, dust uint64, sortByExpirationTime bool,
|
boardingUtxos []types.Utxo,
|
||||||
) ([]client.DescriptorVtxo, uint64, error) {
|
vtxos []client.DescriptorVtxo,
|
||||||
selected := make([]client.DescriptorVtxo, 0)
|
amount,
|
||||||
notSelected := make([]client.DescriptorVtxo, 0)
|
dust uint64,
|
||||||
|
sortByExpirationTime bool,
|
||||||
|
) ([]types.Utxo, []client.DescriptorVtxo, uint64, error) {
|
||||||
|
selected, notSelected := make([]client.DescriptorVtxo, 0), make([]client.DescriptorVtxo, 0)
|
||||||
|
selectedBoarding, notSelectedBoarding := make([]types.Utxo, 0), make([]types.Utxo, 0)
|
||||||
selectedAmount := uint64(0)
|
selectedAmount := uint64(0)
|
||||||
|
|
||||||
if sortByExpirationTime {
|
if sortByExpirationTime {
|
||||||
@@ -38,6 +43,20 @@ func CoinSelect(
|
|||||||
|
|
||||||
return vtxos[i].ExpiresAt.Before(*vtxos[j].ExpiresAt)
|
return vtxos[i].ExpiresAt.Before(*vtxos[j].ExpiresAt)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
sort.SliceStable(boardingUtxos, func(i, j int) bool {
|
||||||
|
return boardingUtxos[i].SpendableAt.Before(boardingUtxos[j].SpendableAt)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, boardingUtxo := range boardingUtxos {
|
||||||
|
if selectedAmount >= amount {
|
||||||
|
notSelectedBoarding = append(notSelectedBoarding, boardingUtxo)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedBoarding = append(selectedBoarding, boardingUtxo)
|
||||||
|
selectedAmount += boardingUtxo.Amount
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, vtxo := range vtxos {
|
for _, vtxo := range vtxos {
|
||||||
@@ -51,7 +70,7 @@ func CoinSelect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if selectedAmount < amount {
|
if selectedAmount < amount {
|
||||||
return nil, 0, fmt.Errorf("not enough funds to cover amount %d", amount)
|
return nil, nil, 0, fmt.Errorf("not enough funds to cover amount %d", amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
change := selectedAmount - amount
|
change := selectedAmount - amount
|
||||||
@@ -60,10 +79,13 @@ func CoinSelect(
|
|||||||
if len(notSelected) > 0 {
|
if len(notSelected) > 0 {
|
||||||
selected = append(selected, notSelected[0])
|
selected = append(selected, notSelected[0])
|
||||||
change += notSelected[0].Amount
|
change += notSelected[0].Amount
|
||||||
|
} else if len(notSelectedBoarding) > 0 {
|
||||||
|
selectedBoarding = append(selectedBoarding, notSelectedBoarding[0])
|
||||||
|
change += notSelectedBoarding[0].Amount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return selected, change, nil
|
return selectedBoarding, selected, change, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseLiquidAddress(addr string) (
|
func ParseLiquidAddress(addr string) (
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package arksdk
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ark-network/ark/pkg/client-sdk/client"
|
||||||
grpcclient "github.com/ark-network/ark/pkg/client-sdk/client/grpc"
|
grpcclient "github.com/ark-network/ark/pkg/client-sdk/client/grpc"
|
||||||
restclient "github.com/ark-network/ark/pkg/client-sdk/client/rest"
|
restclient "github.com/ark-network/ark/pkg/client-sdk/client/rest"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
|
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
|
||||||
@@ -123,3 +124,10 @@ type balanceRes struct {
|
|||||||
offchainBalanceByExpiration map[int64]uint64
|
offchainBalanceByExpiration map[int64]uint64
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CoinSelectOptions struct {
|
||||||
|
// If true, coin selector will select coins closest to expiry first.
|
||||||
|
WithExpirySorting bool
|
||||||
|
// If specified, coin selector will select only coins in the list.
|
||||||
|
OutpointsFilter []client.Outpoint
|
||||||
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ type Transaction struct {
|
|||||||
TransactionKey
|
TransactionKey
|
||||||
Amount uint64
|
Amount uint64
|
||||||
Type TxType
|
Type TxType
|
||||||
IsPending bool
|
Settled bool
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,3 +103,19 @@ type TransactionEvent struct {
|
|||||||
Tx Transaction
|
Tx Transaction
|
||||||
Event EventType
|
Event EventType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Utxo struct {
|
||||||
|
Txid string
|
||||||
|
VOut uint32
|
||||||
|
Amount uint64
|
||||||
|
Asset string // liquid only
|
||||||
|
Delay uint
|
||||||
|
SpendableAt time.Time
|
||||||
|
CreatedAt time.Time
|
||||||
|
Descriptor string
|
||||||
|
Spent bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Utxo) Sequence() (uint32, error) {
|
||||||
|
return common.BIP68Sequence(u.Delay)
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func init() {
|
|||||||
js.Global().Set("sendOnChain", SendOnChainWrapper())
|
js.Global().Set("sendOnChain", SendOnChainWrapper())
|
||||||
js.Global().Set("sendOffChain", SendOffChainWrapper())
|
js.Global().Set("sendOffChain", SendOffChainWrapper())
|
||||||
js.Global().Set("sendAsync", SendAsyncWrapper())
|
js.Global().Set("sendAsync", SendAsyncWrapper())
|
||||||
js.Global().Set("claim", ClaimWrapper())
|
js.Global().Set("settle", SettleWrapper())
|
||||||
js.Global().Set("unilateralRedeem", UnilateralRedeemWrapper())
|
js.Global().Set("unilateralRedeem", UnilateralRedeemWrapper())
|
||||||
js.Global().Set("collaborativeRedeem", CollaborativeRedeemWrapper())
|
js.Global().Set("collaborativeRedeem", CollaborativeRedeemWrapper())
|
||||||
js.Global().Set("getTransactionHistory", GetTransactionHistoryWrapper())
|
js.Global().Set("getTransactionHistory", GetTransactionHistoryWrapper())
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
arksdk "github.com/ark-network/ark/pkg/client-sdk"
|
arksdk "github.com/ark-network/ark/pkg/client-sdk"
|
||||||
|
"github.com/ark-network/ark/pkg/client-sdk/client"
|
||||||
"github.com/ark-network/ark/pkg/client-sdk/wallet"
|
"github.com/ark-network/ark/pkg/client-sdk/wallet"
|
||||||
singlekeywallet "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey"
|
singlekeywallet "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey"
|
||||||
)
|
)
|
||||||
@@ -186,17 +187,17 @@ func SendOnChainWrapper() js.Func {
|
|||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, errors.New("invalid number of args")
|
return nil, errors.New("invalid number of args")
|
||||||
}
|
}
|
||||||
receivers := make([]arksdk.Receiver, args[0].Length())
|
|
||||||
for i := 0; i < args[0].Length(); i++ {
|
receivers, err := parseReceivers(args[0])
|
||||||
receiver := args[0].Index(i)
|
if err != nil {
|
||||||
receivers[i] = arksdk.NewBitcoinReceiver(
|
return nil, err
|
||||||
receiver.Get("To").String(), uint64(receiver.Get("Amount").Int()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
txID, err := arkSdkClient.SendOnChain(
|
if receivers == nil || len(receivers) == 0 {
|
||||||
context.Background(), receivers,
|
return nil, errors.New("no receivers specified")
|
||||||
)
|
}
|
||||||
|
|
||||||
|
txID, err := arkSdkClient.SendOnChain(context.Background(), receivers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -209,13 +210,11 @@ func SendOffChainWrapper() js.Func {
|
|||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return nil, errors.New("invalid number of args")
|
return nil, errors.New("invalid number of args")
|
||||||
}
|
}
|
||||||
|
|
||||||
withExpiryCoinselect := args[0].Bool()
|
withExpiryCoinselect := args[0].Bool()
|
||||||
receivers := make([]arksdk.Receiver, args[1].Length())
|
receivers, err := parseReceivers(args[0])
|
||||||
for i := 0; i < args[1].Length(); i++ {
|
if err != nil {
|
||||||
receiver := args[1].Index(i)
|
return nil, err
|
||||||
receivers[i] = arksdk.NewBitcoinReceiver(
|
|
||||||
receiver.Get("To").String(), uint64(receiver.Get("Amount").Int()),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
txID, err := arkSdkClient.SendOffChain(
|
txID, err := arkSdkClient.SendOffChain(
|
||||||
@@ -233,13 +232,15 @@ func SendAsyncWrapper() js.Func {
|
|||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return nil, errors.New("invalid number of args")
|
return nil, errors.New("invalid number of args")
|
||||||
}
|
}
|
||||||
|
|
||||||
withExpiryCoinselect := args[0].Bool()
|
withExpiryCoinselect := args[0].Bool()
|
||||||
receivers := make([]arksdk.Receiver, args[1].Length())
|
receivers, err := parseReceivers(args[0])
|
||||||
for i := 0; i < args[1].Length(); i++ {
|
if err != nil {
|
||||||
receiver := args[1].Index(i)
|
return nil, err
|
||||||
receivers[i] = arksdk.NewBitcoinReceiver(
|
}
|
||||||
receiver.Get("To").String(), uint64(receiver.Get("Amount").Int()),
|
|
||||||
)
|
if receivers == nil || len(receivers) == 0 {
|
||||||
|
return nil, errors.New("no receivers specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
txID, err := arkSdkClient.SendAsync(
|
txID, err := arkSdkClient.SendAsync(
|
||||||
@@ -252,13 +253,13 @@ func SendAsyncWrapper() js.Func {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClaimWrapper() js.Func {
|
func SettleWrapper() js.Func {
|
||||||
return JSPromise(func(args []js.Value) (interface{}, error) {
|
return JSPromise(func(args []js.Value) (interface{}, error) {
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
return nil, errors.New("invalid number of args")
|
return nil, errors.New("invalid number of args")
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := arkSdkClient.Claim(context.Background())
|
resp, err := arkSdkClient.Settle(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -306,7 +307,7 @@ func GetTransactionHistoryWrapper() js.Func {
|
|||||||
"redeemTxid": record.RedeemTxid,
|
"redeemTxid": record.RedeemTxid,
|
||||||
"amount": strconv.Itoa(int(record.Amount)),
|
"amount": strconv.Itoa(int(record.Amount)),
|
||||||
"type": record.Type,
|
"type": record.Type,
|
||||||
"isPending": record.IsPending,
|
"settled": record.Settled,
|
||||||
"createdAt": record.CreatedAt.Format(time.RFC3339),
|
"createdAt": record.CreatedAt.Format(time.RFC3339),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -433,3 +434,63 @@ func JSPromise(fn promise) js.Func {
|
|||||||
return promiseConstructor.New(handler)
|
return promiseConstructor.New(handler)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseReceivers(jsReceivers js.Value) ([]arksdk.Receiver, error) {
|
||||||
|
if jsReceivers.IsNull() || jsReceivers.IsUndefined() {
|
||||||
|
return nil, nil // Return nil slice if input is null or undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if jsReceivers.Type() != js.TypeObject || jsReceivers.Get("length").Type() != js.TypeNumber {
|
||||||
|
return nil, errors.New("invalid receivers argument: expected array")
|
||||||
|
}
|
||||||
|
|
||||||
|
length := jsReceivers.Length()
|
||||||
|
if length == 0 {
|
||||||
|
return []arksdk.Receiver{}, nil // Return empty slice if input array is empty
|
||||||
|
}
|
||||||
|
|
||||||
|
receivers := make([]arksdk.Receiver, length)
|
||||||
|
for i := 0; i < length; i++ {
|
||||||
|
receiver := jsReceivers.Index(i)
|
||||||
|
if receiver.Type() != js.TypeObject {
|
||||||
|
return nil, fmt.Errorf("invalid receiver at index %d: expected object", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
to := receiver.Get("To")
|
||||||
|
amount := receiver.Get("Amount")
|
||||||
|
if to.Type() != js.TypeString || amount.Type() != js.TypeNumber {
|
||||||
|
return nil, fmt.Errorf("invalid receiver at index %d: expected 'To' (string) and 'Amount' (number)", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
receivers[i] = arksdk.NewBitcoinReceiver(to.String(), uint64(amount.Int()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return receivers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseOutpoints(jsOutpoints js.Value) ([]client.Outpoint, error) {
|
||||||
|
if jsOutpoints.Length() == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
outpoints := make([]client.Outpoint, jsOutpoints.Length())
|
||||||
|
for i := 0; i < jsOutpoints.Length(); i++ {
|
||||||
|
jsOutpoint := jsOutpoints.Index(i)
|
||||||
|
if jsOutpoint.Type() != js.TypeObject {
|
||||||
|
return nil, fmt.Errorf("invalid outpoint at index %d: expected object", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
txid := jsOutpoint.Get("Txid")
|
||||||
|
vout := jsOutpoint.Get("Vout")
|
||||||
|
if txid.Type() != js.TypeString || vout.Type() != js.TypeNumber {
|
||||||
|
return nil, fmt.Errorf("invalid outpoint at index %d: expected 'Txid' (string) and 'Vout' (number)", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
outpoints[i] = client.Outpoint{
|
||||||
|
Txid: txid.String(),
|
||||||
|
VOut: uint32(vout.Int()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outpoints, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,5 +39,3 @@ func PrintBuildInfo() {
|
|||||||
func GetVersion() string {
|
func GetVersion() string {
|
||||||
return Version
|
return Version
|
||||||
}
|
}
|
||||||
|
|
||||||
// You can add more build-related functions here as needed
|
|
||||||
|
|||||||
@@ -21,8 +21,3 @@ func main() {
|
|||||||
println("ARK SDK WebAssembly module initialized")
|
println("ARK SDK WebAssembly module initialized")
|
||||||
<-c
|
<-c
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
// You can add any additional initialization here if needed
|
|
||||||
// This runs before the main function
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ help:
|
|||||||
## intergrationtest: runs integration tests
|
## intergrationtest: runs integration tests
|
||||||
integrationtest:
|
integrationtest:
|
||||||
@echo "Running integration tests..."
|
@echo "Running integration tests..."
|
||||||
@go test -v -count 1 -timeout 400s github.com/ark-network/ark/server/test/e2e/covenant
|
@go test -v -count 1 -timeout 500s github.com/ark-network/ark/server/test/e2e/covenant
|
||||||
@go test -v -count 1 -timeout 400s github.com/ark-network/ark/server/test/e2e/covenantless
|
@go test -v -count 1 -timeout 500s github.com/ark-network/ark/server/test/e2e/covenantless
|
||||||
|
|
||||||
## lint: lint codebase
|
## lint: lint codebase
|
||||||
lint:
|
lint:
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ type covenantlessService struct {
|
|||||||
currentRoundLock sync.Mutex
|
currentRoundLock sync.Mutex
|
||||||
currentRound *domain.Round
|
currentRound *domain.Round
|
||||||
treeSigningSessions map[string]*musigSigningSession
|
treeSigningSessions map[string]*musigSigningSession
|
||||||
asyncPaymentsCache map[string]struct { // redeem txid -> receivers
|
asyncPaymentsCache map[string]asyncPaymentData
|
||||||
receivers []domain.Receiver
|
|
||||||
expireAt int64
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCovenantlessService(
|
func NewCovenantlessService(
|
||||||
@@ -69,11 +66,6 @@ func NewCovenantlessService(
|
|||||||
return nil, fmt.Errorf("failed to fetch pubkey: %s", err)
|
return nil, fmt.Errorf("failed to fetch pubkey: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
asyncPaymentsCache := make(map[string]struct {
|
|
||||||
receivers []domain.Receiver
|
|
||||||
expireAt int64
|
|
||||||
})
|
|
||||||
|
|
||||||
svc := &covenantlessService{
|
svc := &covenantlessService{
|
||||||
network: network,
|
network: network,
|
||||||
pubkey: pubkey,
|
pubkey: pubkey,
|
||||||
@@ -90,7 +82,7 @@ func NewCovenantlessService(
|
|||||||
eventsCh: make(chan domain.RoundEvent),
|
eventsCh: make(chan domain.RoundEvent),
|
||||||
transactionEventsCh: make(chan TransactionEvent),
|
transactionEventsCh: make(chan TransactionEvent),
|
||||||
currentRoundLock: sync.Mutex{},
|
currentRoundLock: sync.Mutex{},
|
||||||
asyncPaymentsCache: asyncPaymentsCache,
|
asyncPaymentsCache: make(map[string]asyncPaymentData),
|
||||||
treeSigningSessions: make(map[string]*musigSigningSession),
|
treeSigningSessions: make(map[string]*musigSigningSession),
|
||||||
boardingExitDelay: boardingExitDelay,
|
boardingExitDelay: boardingExitDelay,
|
||||||
}
|
}
|
||||||
@@ -269,19 +261,16 @@ func (s *covenantlessService) CompleteAsyncPayment(
|
|||||||
|
|
||||||
vtxoPubkey := hex.EncodeToString(schnorr.SerializePubKey(vtxoTapKey))
|
vtxoPubkey := hex.EncodeToString(schnorr.SerializePubKey(vtxoTapKey))
|
||||||
|
|
||||||
// all pending except the last one
|
|
||||||
isPending := outIndex < len(asyncPayData.receivers)-1
|
|
||||||
|
|
||||||
vtxos = append(vtxos, domain.Vtxo{
|
vtxos = append(vtxos, domain.Vtxo{
|
||||||
VtxoKey: domain.VtxoKey{
|
VtxoKey: domain.VtxoKey{
|
||||||
Txid: redeemTxid,
|
Txid: redeemTxid,
|
||||||
VOut: uint32(outIndex),
|
VOut: uint32(outIndex),
|
||||||
},
|
},
|
||||||
Pubkey: vtxoPubkey,
|
Pubkey: vtxoPubkey,
|
||||||
Amount: uint64(out.Value),
|
Amount: uint64(out.Value),
|
||||||
ExpireAt: asyncPayData.expireAt,
|
ExpireAt: asyncPayData.expireAt,
|
||||||
RedeemTx: redeemTx,
|
RoundTxid: asyncPayData.roundTxid,
|
||||||
Pending: isPending,
|
RedeemTx: redeemTx,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,6 +327,8 @@ func (s *covenantlessService) CreateAsyncPayment(
|
|||||||
vtxosInputs := make([]domain.Vtxo, 0, len(inputs))
|
vtxosInputs := make([]domain.Vtxo, 0, len(inputs))
|
||||||
|
|
||||||
expiration := vtxos[0].ExpireAt
|
expiration := vtxos[0].ExpireAt
|
||||||
|
roundTxid := vtxos[0].RoundTxid
|
||||||
|
|
||||||
for _, vtxo := range vtxos {
|
for _, vtxo := range vtxos {
|
||||||
if vtxo.Spent {
|
if vtxo.Spent {
|
||||||
return "", fmt.Errorf("all vtxos must be unspent")
|
return "", fmt.Errorf("all vtxos must be unspent")
|
||||||
@@ -350,11 +341,9 @@ func (s *covenantlessService) CreateAsyncPayment(
|
|||||||
if vtxo.Swept {
|
if vtxo.Swept {
|
||||||
return "", fmt.Errorf("all vtxos must be swept")
|
return "", fmt.Errorf("all vtxos must be swept")
|
||||||
}
|
}
|
||||||
if vtxo.Pending {
|
|
||||||
return "", fmt.Errorf("all vtxos must be claimed")
|
|
||||||
}
|
|
||||||
|
|
||||||
if vtxo.ExpireAt < expiration {
|
if vtxo.ExpireAt < expiration {
|
||||||
|
roundTxid = vtxo.RoundTxid
|
||||||
expiration = vtxo.ExpireAt
|
expiration = vtxo.ExpireAt
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,12 +362,10 @@ func (s *covenantlessService) CreateAsyncPayment(
|
|||||||
return "", fmt.Errorf("failed to parse redeem tx: %s", err)
|
return "", fmt.Errorf("failed to parse redeem tx: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.asyncPaymentsCache[redeemPtx.UnsignedTx.TxID()] = struct {
|
s.asyncPaymentsCache[redeemPtx.UnsignedTx.TxID()] = asyncPaymentData{
|
||||||
receivers []domain.Receiver
|
|
||||||
expireAt int64
|
|
||||||
}{
|
|
||||||
receivers: receivers,
|
receivers: receivers,
|
||||||
expireAt: expiration,
|
expireAt: expiration,
|
||||||
|
roundTxid: roundTxid,
|
||||||
}
|
}
|
||||||
|
|
||||||
return redeemTx, nil
|
return redeemTx, nil
|
||||||
@@ -1588,6 +1575,12 @@ func findForfeitTxBitcoin(
|
|||||||
return "", fmt.Errorf("forfeit tx not found")
|
return "", fmt.Errorf("forfeit tx not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type asyncPaymentData struct {
|
||||||
|
receivers []domain.Receiver
|
||||||
|
expireAt int64
|
||||||
|
roundTxid string
|
||||||
|
}
|
||||||
|
|
||||||
// musigSigningSession holds the state of ephemeral nonces and signatures in order to coordinate the signing of the tree
|
// musigSigningSession holds the state of ephemeral nonces and signatures in order to coordinate the signing of the tree
|
||||||
type musigSigningSession struct {
|
type musigSigningSession struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
|||||||
@@ -166,6 +166,24 @@ func (m *paymentsMap) update(payment domain.Payment) error {
|
|||||||
return fmt.Errorf("payment %s not found", payment.Id)
|
return fmt.Errorf("payment %s not found", payment.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sumOfInputs := uint64(0)
|
||||||
|
for _, input := range payment.Inputs {
|
||||||
|
sumOfInputs += input.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, boardingInput := range p.boardingInputs {
|
||||||
|
sumOfInputs += boardingInput.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
sumOfOutputs := uint64(0)
|
||||||
|
for _, receiver := range payment.Receivers {
|
||||||
|
sumOfOutputs += receiver.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
if sumOfInputs != sumOfOutputs {
|
||||||
|
return fmt.Errorf("sum of inputs %d does not match sum of outputs %d", sumOfInputs, sumOfOutputs)
|
||||||
|
}
|
||||||
|
|
||||||
p.Payment = payment
|
p.Payment = payment
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -123,5 +123,4 @@ type Vtxo struct {
|
|||||||
Swept bool
|
Swept bool
|
||||||
ExpireAt int64
|
ExpireAt int64
|
||||||
RedeemTx string // empty if in-round vtxo
|
RedeemTx string // empty if in-round vtxo
|
||||||
Pending bool
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ CREATE TABLE IF NOT EXISTS vtxo (
|
|||||||
expire_at INTEGER NOT NULL,
|
expire_at INTEGER NOT NULL,
|
||||||
payment_id TEXT,
|
payment_id TEXT,
|
||||||
redeem_tx TEXT,
|
redeem_tx TEXT,
|
||||||
pending BOOLEAN NOT NULL,
|
|
||||||
PRIMARY KEY (txid, vout),
|
PRIMARY KEY (txid, vout),
|
||||||
FOREIGN KEY (payment_id) REFERENCES payment(id)
|
FOREIGN KEY (payment_id) REFERENCES payment(id)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ type PaymentVtxoVw struct {
|
|||||||
ExpireAt sql.NullInt64
|
ExpireAt sql.NullInt64
|
||||||
PaymentID sql.NullString
|
PaymentID sql.NullString
|
||||||
RedeemTx sql.NullString
|
RedeemTx sql.NullString
|
||||||
Pending sql.NullBool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Receiver struct {
|
type Receiver struct {
|
||||||
@@ -100,5 +99,4 @@ type Vtxo struct {
|
|||||||
ExpireAt int64
|
ExpireAt int64
|
||||||
PaymentID sql.NullString
|
PaymentID sql.NullString
|
||||||
RedeemTx sql.NullString
|
RedeemTx sql.NullString
|
||||||
Pending bool
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func (q *Queries) MarkVtxoAsSwept(ctx context.Context, arg MarkVtxoAsSweptParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectNotRedeemedVtxos = `-- name: SelectNotRedeemedVtxos :many
|
const selectNotRedeemedVtxos = `-- name: SelectNotRedeemedVtxos :many
|
||||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx, vtxo.pending FROM vtxo
|
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||||
WHERE redeemed = false
|
WHERE redeemed = false
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -84,7 +84,6 @@ func (q *Queries) SelectNotRedeemedVtxos(ctx context.Context) ([]SelectNotRedeem
|
|||||||
&i.Vtxo.ExpireAt,
|
&i.Vtxo.ExpireAt,
|
||||||
&i.Vtxo.PaymentID,
|
&i.Vtxo.PaymentID,
|
||||||
&i.Vtxo.RedeemTx,
|
&i.Vtxo.RedeemTx,
|
||||||
&i.Vtxo.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -100,7 +99,7 @@ func (q *Queries) SelectNotRedeemedVtxos(ctx context.Context) ([]SelectNotRedeem
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectNotRedeemedVtxosWithPubkey = `-- name: SelectNotRedeemedVtxosWithPubkey :many
|
const selectNotRedeemedVtxosWithPubkey = `-- name: SelectNotRedeemedVtxosWithPubkey :many
|
||||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx, vtxo.pending FROM vtxo
|
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||||
WHERE redeemed = false AND pubkey = ?
|
WHERE redeemed = false AND pubkey = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -130,7 +129,6 @@ func (q *Queries) SelectNotRedeemedVtxosWithPubkey(ctx context.Context, pubkey s
|
|||||||
&i.Vtxo.ExpireAt,
|
&i.Vtxo.ExpireAt,
|
||||||
&i.Vtxo.PaymentID,
|
&i.Vtxo.PaymentID,
|
||||||
&i.Vtxo.RedeemTx,
|
&i.Vtxo.RedeemTx,
|
||||||
&i.Vtxo.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -209,7 +207,7 @@ SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended,
|
|||||||
round_payment_vw.id, round_payment_vw.round_id,
|
round_payment_vw.id, round_payment_vw.round_id,
|
||||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx, payment_vtxo_vw.pending
|
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||||
FROM round
|
FROM round
|
||||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||||
@@ -275,7 +273,6 @@ func (q *Queries) SelectRoundWithRoundId(ctx context.Context, id string) ([]Sele
|
|||||||
&i.PaymentVtxoVw.ExpireAt,
|
&i.PaymentVtxoVw.ExpireAt,
|
||||||
&i.PaymentVtxoVw.PaymentID,
|
&i.PaymentVtxoVw.PaymentID,
|
||||||
&i.PaymentVtxoVw.RedeemTx,
|
&i.PaymentVtxoVw.RedeemTx,
|
||||||
&i.PaymentVtxoVw.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -295,7 +292,7 @@ SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended,
|
|||||||
round_payment_vw.id, round_payment_vw.round_id,
|
round_payment_vw.id, round_payment_vw.round_id,
|
||||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx, payment_vtxo_vw.pending
|
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||||
FROM round
|
FROM round
|
||||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||||
@@ -361,7 +358,6 @@ func (q *Queries) SelectRoundWithRoundTxId(ctx context.Context, txid string) ([]
|
|||||||
&i.PaymentVtxoVw.ExpireAt,
|
&i.PaymentVtxoVw.ExpireAt,
|
||||||
&i.PaymentVtxoVw.PaymentID,
|
&i.PaymentVtxoVw.PaymentID,
|
||||||
&i.PaymentVtxoVw.RedeemTx,
|
&i.PaymentVtxoVw.RedeemTx,
|
||||||
&i.PaymentVtxoVw.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -381,7 +377,7 @@ SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended,
|
|||||||
round_payment_vw.id, round_payment_vw.round_id,
|
round_payment_vw.id, round_payment_vw.round_id,
|
||||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx, payment_vtxo_vw.pending
|
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||||
FROM round
|
FROM round
|
||||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||||
@@ -447,7 +443,6 @@ func (q *Queries) SelectSweepableRounds(ctx context.Context) ([]SelectSweepableR
|
|||||||
&i.PaymentVtxoVw.ExpireAt,
|
&i.PaymentVtxoVw.ExpireAt,
|
||||||
&i.PaymentVtxoVw.PaymentID,
|
&i.PaymentVtxoVw.PaymentID,
|
||||||
&i.PaymentVtxoVw.RedeemTx,
|
&i.PaymentVtxoVw.RedeemTx,
|
||||||
&i.PaymentVtxoVw.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -463,7 +458,7 @@ func (q *Queries) SelectSweepableRounds(ctx context.Context) ([]SelectSweepableR
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectSweepableVtxos = `-- name: SelectSweepableVtxos :many
|
const selectSweepableVtxos = `-- name: SelectSweepableVtxos :many
|
||||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx, vtxo.pending FROM vtxo
|
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||||
WHERE redeemed = false AND swept = false
|
WHERE redeemed = false AND swept = false
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -493,7 +488,6 @@ func (q *Queries) SelectSweepableVtxos(ctx context.Context) ([]SelectSweepableVt
|
|||||||
&i.Vtxo.ExpireAt,
|
&i.Vtxo.ExpireAt,
|
||||||
&i.Vtxo.PaymentID,
|
&i.Vtxo.PaymentID,
|
||||||
&i.Vtxo.RedeemTx,
|
&i.Vtxo.RedeemTx,
|
||||||
&i.Vtxo.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -513,7 +507,7 @@ SELECT round.id, round.starting_timestamp, round.ending_timestamp, round.ended,
|
|||||||
round_payment_vw.id, round_payment_vw.round_id,
|
round_payment_vw.id, round_payment_vw.round_id,
|
||||||
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
round_tx_vw.id, round_tx_vw.tx, round_tx_vw.round_id, round_tx_vw.type, round_tx_vw.position, round_tx_vw.txid, round_tx_vw.tree_level, round_tx_vw.parent_txid, round_tx_vw.is_leaf,
|
||||||
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
payment_receiver_vw.payment_id, payment_receiver_vw.pubkey, payment_receiver_vw.onchain_address, payment_receiver_vw.amount,
|
||||||
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx, payment_vtxo_vw.pending
|
payment_vtxo_vw.txid, payment_vtxo_vw.vout, payment_vtxo_vw.pubkey, payment_vtxo_vw.amount, payment_vtxo_vw.pool_tx, payment_vtxo_vw.spent_by, payment_vtxo_vw.spent, payment_vtxo_vw.redeemed, payment_vtxo_vw.swept, payment_vtxo_vw.expire_at, payment_vtxo_vw.payment_id, payment_vtxo_vw.redeem_tx
|
||||||
FROM round
|
FROM round
|
||||||
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
LEFT OUTER JOIN round_payment_vw ON round.id=round_payment_vw.round_id
|
||||||
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
LEFT OUTER JOIN round_tx_vw ON round.id=round_tx_vw.round_id
|
||||||
@@ -579,7 +573,6 @@ func (q *Queries) SelectSweptRounds(ctx context.Context) ([]SelectSweptRoundsRow
|
|||||||
&i.PaymentVtxoVw.ExpireAt,
|
&i.PaymentVtxoVw.ExpireAt,
|
||||||
&i.PaymentVtxoVw.PaymentID,
|
&i.PaymentVtxoVw.PaymentID,
|
||||||
&i.PaymentVtxoVw.RedeemTx,
|
&i.PaymentVtxoVw.RedeemTx,
|
||||||
&i.PaymentVtxoVw.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -595,7 +588,7 @@ func (q *Queries) SelectSweptRounds(ctx context.Context) ([]SelectSweptRoundsRow
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selectVtxoByOutpoint = `-- name: SelectVtxoByOutpoint :one
|
const selectVtxoByOutpoint = `-- name: SelectVtxoByOutpoint :one
|
||||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx, vtxo.pending FROM vtxo
|
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||||
WHERE txid = ? AND vout = ?
|
WHERE txid = ? AND vout = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -624,13 +617,12 @@ func (q *Queries) SelectVtxoByOutpoint(ctx context.Context, arg SelectVtxoByOutp
|
|||||||
&i.Vtxo.ExpireAt,
|
&i.Vtxo.ExpireAt,
|
||||||
&i.Vtxo.PaymentID,
|
&i.Vtxo.PaymentID,
|
||||||
&i.Vtxo.RedeemTx,
|
&i.Vtxo.RedeemTx,
|
||||||
&i.Vtxo.Pending,
|
|
||||||
)
|
)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectVtxosByPoolTxid = `-- name: SelectVtxosByPoolTxid :many
|
const selectVtxosByPoolTxid = `-- name: SelectVtxosByPoolTxid :many
|
||||||
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx, vtxo.pending FROM vtxo
|
SELECT vtxo.txid, vtxo.vout, vtxo.pubkey, vtxo.amount, vtxo.pool_tx, vtxo.spent_by, vtxo.spent, vtxo.redeemed, vtxo.swept, vtxo.expire_at, vtxo.payment_id, vtxo.redeem_tx FROM vtxo
|
||||||
WHERE pool_tx = ?
|
WHERE pool_tx = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
@@ -660,7 +652,6 @@ func (q *Queries) SelectVtxosByPoolTxid(ctx context.Context, poolTx string) ([]S
|
|||||||
&i.Vtxo.ExpireAt,
|
&i.Vtxo.ExpireAt,
|
||||||
&i.Vtxo.PaymentID,
|
&i.Vtxo.PaymentID,
|
||||||
&i.Vtxo.RedeemTx,
|
&i.Vtxo.RedeemTx,
|
||||||
&i.Vtxo.Pending,
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -847,8 +838,8 @@ func (q *Queries) UpsertTransaction(ctx context.Context, arg UpsertTransactionPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
const upsertVtxo = `-- name: UpsertVtxo :exec
|
const upsertVtxo = `-- name: UpsertVtxo :exec
|
||||||
INSERT INTO vtxo (txid, vout, pubkey, amount, pool_tx, spent_by, spent, redeemed, swept, expire_at, redeem_tx, pending)
|
INSERT INTO vtxo (txid, vout, pubkey, amount, pool_tx, spent_by, spent, redeemed, swept, expire_at, redeem_tx)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SET
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SET
|
||||||
pubkey = EXCLUDED.pubkey,
|
pubkey = EXCLUDED.pubkey,
|
||||||
amount = EXCLUDED.amount,
|
amount = EXCLUDED.amount,
|
||||||
pool_tx = EXCLUDED.pool_tx,
|
pool_tx = EXCLUDED.pool_tx,
|
||||||
@@ -857,8 +848,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SE
|
|||||||
redeemed = EXCLUDED.redeemed,
|
redeemed = EXCLUDED.redeemed,
|
||||||
swept = EXCLUDED.swept,
|
swept = EXCLUDED.swept,
|
||||||
expire_at = EXCLUDED.expire_at,
|
expire_at = EXCLUDED.expire_at,
|
||||||
redeem_tx = EXCLUDED.redeem_tx,
|
redeem_tx = EXCLUDED.redeem_tx
|
||||||
pending = EXCLUDED.pending
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type UpsertVtxoParams struct {
|
type UpsertVtxoParams struct {
|
||||||
@@ -873,7 +863,6 @@ type UpsertVtxoParams struct {
|
|||||||
Swept bool
|
Swept bool
|
||||||
ExpireAt int64
|
ExpireAt int64
|
||||||
RedeemTx sql.NullString
|
RedeemTx sql.NullString
|
||||||
Pending bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) UpsertVtxo(ctx context.Context, arg UpsertVtxoParams) error {
|
func (q *Queries) UpsertVtxo(ctx context.Context, arg UpsertVtxoParams) error {
|
||||||
@@ -889,7 +878,6 @@ func (q *Queries) UpsertVtxo(ctx context.Context, arg UpsertVtxoParams) error {
|
|||||||
arg.Swept,
|
arg.Swept,
|
||||||
arg.ExpireAt,
|
arg.ExpireAt,
|
||||||
arg.RedeemTx,
|
arg.RedeemTx,
|
||||||
arg.Pending,
|
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,8 +112,8 @@ SELECT id FROM round WHERE starting_timestamp > ? AND starting_timestamp < ?;
|
|||||||
SELECT id FROM round;
|
SELECT id FROM round;
|
||||||
|
|
||||||
-- name: UpsertVtxo :exec
|
-- name: UpsertVtxo :exec
|
||||||
INSERT INTO vtxo (txid, vout, pubkey, amount, pool_tx, spent_by, spent, redeemed, swept, expire_at, redeem_tx, pending)
|
INSERT INTO vtxo (txid, vout, pubkey, amount, pool_tx, spent_by, spent, redeemed, swept, expire_at, redeem_tx)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SET
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SET
|
||||||
pubkey = EXCLUDED.pubkey,
|
pubkey = EXCLUDED.pubkey,
|
||||||
amount = EXCLUDED.amount,
|
amount = EXCLUDED.amount,
|
||||||
pool_tx = EXCLUDED.pool_tx,
|
pool_tx = EXCLUDED.pool_tx,
|
||||||
@@ -122,8 +122,7 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(txid, vout) DO UPDATE SE
|
|||||||
redeemed = EXCLUDED.redeemed,
|
redeemed = EXCLUDED.redeemed,
|
||||||
swept = EXCLUDED.swept,
|
swept = EXCLUDED.swept,
|
||||||
expire_at = EXCLUDED.expire_at,
|
expire_at = EXCLUDED.expire_at,
|
||||||
redeem_tx = EXCLUDED.redeem_tx,
|
redeem_tx = EXCLUDED.redeem_tx;
|
||||||
pending = EXCLUDED.pending;
|
|
||||||
|
|
||||||
-- name: SelectSweepableVtxos :many
|
-- name: SelectSweepableVtxos :many
|
||||||
SELECT sqlc.embed(vtxo) FROM vtxo
|
SELECT sqlc.embed(vtxo) FROM vtxo
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ func (v *vxtoRepository) AddVtxos(ctx context.Context, vtxos []domain.Vtxo) erro
|
|||||||
Swept: vtxo.Swept,
|
Swept: vtxo.Swept,
|
||||||
ExpireAt: vtxo.ExpireAt,
|
ExpireAt: vtxo.ExpireAt,
|
||||||
RedeemTx: sql.NullString{String: vtxo.RedeemTx, Valid: true},
|
RedeemTx: sql.NullString{String: vtxo.RedeemTx, Valid: true},
|
||||||
Pending: vtxo.Pending,
|
|
||||||
},
|
},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -259,7 +258,6 @@ func rowToVtxo(row queries.Vtxo) domain.Vtxo {
|
|||||||
Swept: row.Swept,
|
Swept: row.Swept,
|
||||||
ExpireAt: row.ExpireAt,
|
ExpireAt: row.ExpireAt,
|
||||||
RedeemTx: row.RedeemTx.String,
|
RedeemTx: row.RedeemTx.String,
|
||||||
Pending: row.Pending,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -782,9 +782,9 @@ func (s *service) Status(ctx context.Context) (ports.WalletStatus, error) {
|
|||||||
|
|
||||||
w := s.wallet.InternalWallet()
|
w := s.wallet.InternalWallet()
|
||||||
return status{
|
return status{
|
||||||
true,
|
initialized: true,
|
||||||
!w.Manager.IsLocked(),
|
unlocked: !w.Manager.IsLocked(),
|
||||||
w.ChainSynced(),
|
synced: s.isSynced,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func (v vtxoList) toProto() []*arkv1.Vtxo {
|
|||||||
SpentBy: vv.SpentBy,
|
SpentBy: vv.SpentBy,
|
||||||
Swept: vv.Swept,
|
Swept: vv.Swept,
|
||||||
RedeemTx: vv.RedeemTx,
|
RedeemTx: vv.RedeemTx,
|
||||||
Pending: vv.Pending,
|
IsOor: len(vv.RedeemTx) > 0,
|
||||||
Pubkey: vv.Pubkey,
|
Pubkey: vv.Pubkey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func TestSendOffchain(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runArkCommand("claim", "--password", utils.Password)
|
_, err = runArkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
@@ -101,7 +101,7 @@ func TestUnilateralExit(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runArkCommand("claim", "--password", utils.Password)
|
_, err = runArkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
@@ -142,7 +142,7 @@ func TestCollaborativeExit(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runArkCommand("claim", "--password", utils.Password)
|
_, err = runArkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
@@ -164,7 +164,7 @@ func TestReactToSpentVtxosRedemption(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = client.Claim(ctx)
|
_, err = client.Settle(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
@@ -216,7 +216,7 @@ func TestSweep(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runArkCommand("claim", "--password", utils.Password)
|
_, err = runArkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func TestSendOffchain(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runClarkCommand("claim", "--password", utils.Password)
|
_, err = runClarkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
@@ -91,7 +91,7 @@ func TestSendOffchain(t *testing.T) {
|
|||||||
require.NoError(t, json.Unmarshal([]byte(balanceStr), &balance))
|
require.NoError(t, json.Unmarshal([]byte(balanceStr), &balance))
|
||||||
require.NotZero(t, balance.Offchain.Total)
|
require.NotZero(t, balance.Offchain.Total)
|
||||||
|
|
||||||
_, err = runClarkCommand("claim", "--password", utils.Password)
|
_, err = runClarkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
balanceStr, err = runClarkCommand("balance")
|
balanceStr, err = runClarkCommand("balance")
|
||||||
@@ -113,7 +113,7 @@ func TestUnilateralExit(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runClarkCommand("claim", "--password", utils.Password)
|
_, err = runClarkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
@@ -155,11 +155,6 @@ func TestCollaborativeExit(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runClarkCommand("claim", "--password", utils.Password)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
|
|
||||||
_, err = runClarkCommand("redeem", "--amount", "1000", "--address", redeemAddress, "--password", utils.Password)
|
_, err = runClarkCommand("redeem", "--amount", "1000", "--address", redeemAddress, "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
@@ -177,7 +172,7 @@ func TestReactToSpentVtxosRedemption(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = client.Claim(ctx)
|
_, err = client.Settle(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = client.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(offchainAddress, 1000)})
|
_, err = client.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(offchainAddress, 1000)})
|
||||||
@@ -217,71 +212,105 @@ func TestReactToSpentVtxosRedemption(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReactToAsyncSpentVtxosRedemption(t *testing.T) {
|
func TestReactToAsyncSpentVtxosRedemption(t *testing.T) {
|
||||||
t.Run("receiver claimed funds", func(t *testing.T) {
|
ctx := context.Background()
|
||||||
ctx := context.Background()
|
sdkClient, grpcClient := setupArkSDK(t)
|
||||||
sdkClient, grpcClient := setupArkSDK(t)
|
defer grpcClient.Close()
|
||||||
defer grpcClient.Close()
|
|
||||||
|
|
||||||
offchainAddress, boardingAddress, err := sdkClient.Receive(ctx)
|
offchainAddress, boardingAddress, err := sdkClient.Receive(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = utils.RunCommand("nigiri", "faucet", boardingAddress)
|
_, err = utils.RunCommand("nigiri", "faucet", boardingAddress)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
roundId, err := sdkClient.Claim(ctx)
|
roundId, err := sdkClient.Settle(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = utils.GenerateBlock()
|
err = utils.GenerateBlock()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = sdkClient.SendAsync(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(offchainAddress, 1000)})
|
_, err = sdkClient.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(offchainAddress, 1000)})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = sdkClient.Claim(ctx)
|
_, err = sdkClient.Settle(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, spentVtxos, err := sdkClient.ListVtxos(ctx)
|
_, spentVtxos, err := sdkClient.ListVtxos(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, spentVtxos)
|
require.NotEmpty(t, spentVtxos)
|
||||||
|
|
||||||
var vtxo client.Vtxo
|
var vtxo client.Vtxo
|
||||||
|
|
||||||
for _, v := range spentVtxos {
|
for _, v := range spentVtxos {
|
||||||
if v.RoundTxid == roundId {
|
if v.RoundTxid == roundId {
|
||||||
vtxo = v
|
vtxo = v
|
||||||
break
|
break
|
||||||
}
|
|
||||||
}
|
}
|
||||||
require.NotEmpty(t, vtxo)
|
}
|
||||||
|
require.NotEmpty(t, vtxo)
|
||||||
|
|
||||||
round, err := grpcClient.GetRound(ctx, vtxo.RoundTxid)
|
round, err := grpcClient.GetRound(ctx, vtxo.RoundTxid)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expl := explorer.NewExplorer("http://localhost:3000", common.BitcoinRegTest)
|
||||||
|
|
||||||
|
branch, err := redemption.NewCovenantlessRedeemBranch(expl, round.Tree, vtxo)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
txs, err := branch.RedeemPath()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
for _, tx := range txs {
|
||||||
|
_, err := expl.Broadcast(tx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
expl := explorer.NewExplorer("http://localhost:3000", common.BitcoinRegTest)
|
// give time for the ASP to detect and process the fraud
|
||||||
|
time.Sleep(50 * time.Second)
|
||||||
|
|
||||||
branch, err := redemption.NewCovenantlessRedeemBranch(expl, round.Tree, vtxo)
|
balance, err := sdkClient.Balance(ctx, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
txs, err := branch.RedeemPath()
|
require.Empty(t, balance.OnchainBalance.LockedAmount)
|
||||||
require.NoError(t, err)
|
}
|
||||||
|
|
||||||
for _, tx := range txs {
|
func TestChainAsyncPayments(t *testing.T) {
|
||||||
_, err := expl.Broadcast(tx)
|
var receive utils.ArkReceive
|
||||||
require.NoError(t, err)
|
receiveStr, err := runClarkCommand("receive")
|
||||||
}
|
require.NoError(t, err)
|
||||||
|
|
||||||
// give time for the ASP to detect and process the fraud
|
err = json.Unmarshal([]byte(receiveStr), &receive)
|
||||||
time.Sleep(50 * time.Second)
|
require.NoError(t, err)
|
||||||
|
|
||||||
balance, err := sdkClient.Balance(ctx, false)
|
_, err = utils.RunCommand("nigiri", "faucet", receive.Boarding)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.Empty(t, balance.OnchainBalance.LockedAmount)
|
time.Sleep(5 * time.Second)
|
||||||
})
|
|
||||||
|
_, err = runClarkCommand("settle", "--password", utils.Password)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
_, err = runClarkCommand("send", "--amount", "10000", "--to", receive.Offchain, "--password", utils.Password)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var balance utils.ArkBalance
|
||||||
|
balanceStr, err := runClarkCommand("balance")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, json.Unmarshal([]byte(balanceStr), &balance))
|
||||||
|
require.NotZero(t, balance.Offchain.Total)
|
||||||
|
|
||||||
|
_, err = runClarkCommand("send", "--amount", "10000", "--to", receive.Offchain, "--password", utils.Password)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
balanceStr, err = runClarkCommand("balance")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NoError(t, json.Unmarshal([]byte(balanceStr), &balance))
|
||||||
|
require.NotZero(t, balance.Offchain.Total)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAliceSeveralPaymentsToBob(t *testing.T) {
|
func TestAliceSeveralPaymentsToBob(t *testing.T) {
|
||||||
@@ -300,9 +329,6 @@ func TestAliceSeveralPaymentsToBob(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = alice.Claim(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
bobAddress, _, err := bob.Receive(ctx)
|
bobAddress, _, err := bob.Receive(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -315,12 +341,6 @@ func TestAliceSeveralPaymentsToBob(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, bobVtxos, 1)
|
require.Len(t, bobVtxos, 1)
|
||||||
|
|
||||||
_, err = bob.Claim(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
_, err = alice.Claim(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
_, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobAddress, 10000)})
|
_, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobAddress, 10000)})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -339,7 +359,7 @@ func TestAliceSeveralPaymentsToBob(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, bobVtxos, 3)
|
require.Len(t, bobVtxos, 3)
|
||||||
|
|
||||||
_, err = alice.SendAsync(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobAddress, 10000)})
|
_, err = alice.SendOffChain(ctx, false, []arksdk.Receiver{arksdk.NewBitcoinReceiver(bobAddress, 10000)})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
@@ -348,9 +368,6 @@ func TestAliceSeveralPaymentsToBob(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, bobVtxos, 4)
|
require.Len(t, bobVtxos, 4)
|
||||||
|
|
||||||
_, err = alice.Claim(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// bobVtxos should be unique
|
// bobVtxos should be unique
|
||||||
uniqueVtxos := make(map[string]struct{})
|
uniqueVtxos := make(map[string]struct{})
|
||||||
for _, v := range bobVtxos {
|
for _, v := range bobVtxos {
|
||||||
@@ -358,9 +375,7 @@ func TestAliceSeveralPaymentsToBob(t *testing.T) {
|
|||||||
}
|
}
|
||||||
require.Len(t, uniqueVtxos, 4)
|
require.Len(t, uniqueVtxos, 4)
|
||||||
|
|
||||||
_, err = bob.Claim(ctx)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSweep(t *testing.T) {
|
func TestSweep(t *testing.T) {
|
||||||
@@ -376,7 +391,7 @@ func TestSweep(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
_, err = runClarkCommand("claim", "--password", utils.Password)
|
_, err = runClarkCommand("settle", "--password", utils.Password)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
|||||||
Reference in New Issue
Block a user