1
1
use std:: str:: FromStr ;
2
- use std:: sync:: Arc ;
3
2
3
+ use crate :: AccountingContractApi ;
4
4
use alloy:: primitives:: U256 ;
5
5
use anchor_client:: {
6
6
solana_sdk:: {
@@ -14,22 +14,9 @@ use anchor_client::{
14
14
} ;
15
15
use async_trait:: async_trait;
16
16
use sp_core:: ed25519;
17
+ use std:: sync:: Arc ;
17
18
use tracing:: { error, warn} ;
18
19
19
- #[ async_trait]
20
- pub trait AccountingContractApi : Send + Sync {
21
- async fn execute_pay_out_request (
22
- & self ,
23
- beneficiary : Pubkey ,
24
- nonce : u64 ,
25
- amount : U256 ,
26
- ) -> Result < ( ) , ( ) > ;
27
-
28
- async fn get_nonce ( & self , user : Pubkey ) -> Result < u64 , ( ) > ;
29
-
30
- async fn get_balance ( & self ) -> Result < U256 , ( ) > ;
31
- }
32
-
33
20
pub struct AccountingContractClient {
34
21
pub payer : Keypair ,
35
22
pub solana_url : String ,
@@ -58,65 +45,48 @@ impl AccountingContractClient {
58
45
}
59
46
60
47
#[ async_trait]
61
- impl AccountingContractApi for AccountingContractClient {
48
+ impl AccountingContractApi < Pubkey , u64 > for AccountingContractClient {
62
49
async fn execute_pay_out_request (
63
50
& self ,
64
51
beneficiary : Pubkey ,
65
52
nonce : u64 ,
66
53
amount : U256 ,
67
54
) -> Result < ( ) , ( ) > {
68
55
let client = self . create_client ( ) ?;
69
- let program = client. program ( self . program_id ) . map_err ( |e| {
70
- error ! ( "Failed to create program client: {:?}" , e) ;
71
- } ) ?;
72
56
73
- let result = tokio:: task:: spawn_blocking ( move || {
74
- program
75
- . request ( )
76
- . accounts ( accounting_contract:: accounts:: CreatePayRequest {
77
- pay_out_request : Pubkey :: find_program_address (
78
- & [ beneficiary. to_bytes ( ) . as_ref ( ) , & nonce. to_le_bytes ( ) , b"payout_request" ] ,
79
- & program. id ( ) ,
80
- )
81
- . 0 ,
82
- account_nonce : Pubkey :: find_program_address (
83
- & [ beneficiary. to_bytes ( ) . as_ref ( ) , b"nonce" ] ,
84
- & program. id ( ) ,
85
- )
86
- . 0 ,
87
- signer : program. payer ( ) ,
88
- worker : Pubkey :: find_program_address ( & [ b"worker" ] , & program. id ( ) ) . 0 ,
89
- treasury : Pubkey :: find_program_address ( & [ b"treasury" ] , & program. id ( ) ) . 0 ,
90
- beneficiary,
91
- system_program : system_program:: ID ,
92
- } )
93
- . args ( accounting_contract:: instruction:: CreatePayRequest {
94
- amount : amount. try_into ( ) . map_err ( |_| {
95
- error ! ( "Failed to convert U256 to u64" ) ;
96
- anchor_client:: ClientError :: from ( std:: io:: Error :: new (
97
- std:: io:: ErrorKind :: InvalidData ,
98
- "Failed to convert U256 to u64" ,
99
- ) )
100
- } ) ?,
101
- nonce,
102
- } )
103
- . send ( )
104
- } )
105
- . await ;
106
-
107
- match result {
108
- Ok ( anchor_result) => match anchor_result {
109
- Ok ( _) => Ok ( ( ) ) ,
110
- Err ( e) => {
111
- error ! ( "Anchor client error: {:?}" , e) ;
112
- Err ( ( ) )
113
- } ,
114
- } ,
115
- Err ( e) => {
57
+ let program = client. program ( self . program_id ) . expect ( "Failed to create program client" ) ;
58
+
59
+ program
60
+ . request ( )
61
+ . accounts ( accounting_contract:: accounts:: CreatePayRequest {
62
+ pay_out_request : Pubkey :: find_program_address (
63
+ & [ beneficiary. to_bytes ( ) . as_ref ( ) , & nonce. to_le_bytes ( ) , b"payout_request" ] ,
64
+ & program. id ( ) ,
65
+ )
66
+ . 0 ,
67
+ account_nonce : Pubkey :: find_program_address (
68
+ & [ beneficiary. to_bytes ( ) . as_ref ( ) , b"nonce" ] ,
69
+ & program. id ( ) ,
70
+ )
71
+ . 0 ,
72
+ signer : self . payer . pubkey ( ) ,
73
+ worker : Pubkey :: find_program_address ( & [ b"worker" ] , & program. id ( ) ) . 0 ,
74
+ treasury : Pubkey :: find_program_address ( & [ b"treasury" ] , & program. id ( ) ) . 0 ,
75
+ beneficiary,
76
+ system_program : system_program:: ID ,
77
+ } )
78
+ . args ( accounting_contract:: instruction:: CreatePayRequest {
79
+ amount : amount. try_into ( ) . map_err ( |_| {
80
+ error ! ( "Failed to convert U256 amount to u64" ) ;
81
+ } ) ?,
82
+ nonce,
83
+ } )
84
+ . send ( )
85
+ . await
86
+ . map_err ( |e| {
116
87
error ! ( "Failed to execute pay out request: {:?}" , e) ;
117
- Err ( ( ) )
118
- } ,
119
- }
88
+ } ) ?;
89
+ Ok ( ( ) )
120
90
}
121
91
122
92
async fn get_nonce ( & self , user : Pubkey ) -> Result < u64 , ( ) > {
@@ -129,46 +99,29 @@ impl AccountingContractApi for AccountingContractClient {
129
99
let ( account_pubkey, _bump) =
130
100
Pubkey :: find_program_address ( & [ user. to_bytes ( ) . as_ref ( ) , b"nonce" ] , & self . program_id ) ;
131
101
132
- match tokio:: task:: spawn_blocking ( move || program. rpc ( ) . get_account ( & account_pubkey) ) . await
133
- {
102
+ match program. rpc ( ) . get_account ( & account_pubkey) . await {
134
103
// return default nonce 0 when fail to get nonce
135
- Ok ( result) => match result {
136
- Ok ( account) => {
137
- match bincode:: deserialize :: < accounting_contract:: Nonce > ( & account. data [ 8 ..] ) {
138
- Ok ( nonce) => Ok ( nonce. nonce ) ,
139
- Err ( e) => {
140
- error ! ( "Failed deserialize nonce from account {:?}: {:?}" , account, e) ;
141
- Ok ( 0 )
142
- } ,
143
- }
144
- } ,
145
- Err ( e) => {
146
- error ! ( "Failed to get_account {:?}" , e) ;
147
- Ok ( 0 )
148
- } ,
104
+ Ok ( account) => {
105
+ match bincode:: deserialize :: < accounting_contract:: Nonce > ( & account. data [ 8 ..] ) {
106
+ Ok ( nonce) => Ok ( nonce. nonce ) ,
107
+ Err ( e) => {
108
+ error ! ( "Failed deserialize nonce from account {:?}: {:?}" , account, e) ;
109
+ Ok ( 0 )
110
+ } ,
111
+ }
149
112
} ,
150
113
Err ( e) => {
151
- error ! ( "Failed to spawn blocking task: {:?}" , e) ;
152
- Err ( ( ) )
114
+ error ! ( "Failed to get_account {:?}" , e) ;
115
+ Ok ( 0 )
153
116
} ,
154
117
}
155
118
}
156
119
157
120
async fn get_balance ( & self ) -> Result < U256 , ( ) > {
158
121
let client = self . create_client ( ) ?;
159
- let program = client. program ( self . program_id ) . map_err ( |e| {
160
- error ! ( "Failed to create program client: {:?}" , e) ;
161
- } ) ?;
162
122
163
- let payer_pubkey = self . payer . pubkey ( ) ;
164
- let balance_result =
165
- tokio:: task:: spawn_blocking ( move || program. rpc ( ) . get_balance ( & payer_pubkey) )
166
- . await
167
- . map_err ( |e| {
168
- error ! ( "Failed to spawn blocking task: {:?}" , e) ;
169
- } ) ?;
170
-
171
- match balance_result {
123
+ let program = client. program ( self . program_id ) . expect ( "Failed to create program client" ) ;
124
+ match program. rpc ( ) . get_balance ( & self . payer . pubkey ( ) ) . await {
172
125
Ok ( v) => {
173
126
let balance = U256 :: try_from ( v) . map_err ( |err| {
174
127
warn ! ( "Failed to convert balance to U256: {:?}" , err) ;
@@ -185,17 +138,19 @@ impl AccountingContractApi for AccountingContractClient {
185
138
186
139
#[ cfg( feature = "mocks" ) ]
187
140
pub mod mocks {
188
- use crate :: solana :: AccountingContractApi ;
141
+ use crate :: AccountingContractApi ;
189
142
use crate :: U256 ;
190
143
use anchor_client:: solana_sdk:: pubkey:: Pubkey ;
191
144
use async_trait:: async_trait;
192
145
use mockall:: mock;
193
146
194
147
mock ! {
148
+
195
149
pub AccountingContractClient { }
196
150
197
151
#[ async_trait]
198
- impl AccountingContractApi for AccountingContractClient {
152
+ impl AccountingContractApi <Pubkey , u64 > for AccountingContractClient {
153
+
199
154
async fn execute_pay_out_request(
200
155
& self ,
201
156
beneficiary: Pubkey ,
0 commit comments