1
1
import * as grpc from '@grpc/grpc-js' ;
2
+ import { Interface } from 'ethers/lib/utils' ;
2
3
import { TxExecution } from '../proto/exec_pb' ;
3
4
import { CallTx , ContractMeta } from '../proto/payload_pb' ;
4
5
import { ExecutionEventsClient , IExecutionEventsClient } from '../proto/rpcevents_grpc_pb' ;
5
6
import { BlockRange } from '../proto/rpcevents_pb' ;
6
7
import { IQueryClient , QueryClient } from '../proto/rpcquery_grpc_pb' ;
7
- import { GetMetadataParam } from '../proto/rpcquery_pb' ;
8
+ import { GetMetadataParam , StatusParam } from '../proto/rpcquery_pb' ;
8
9
import { ITransactClient , TransactClient } from '../proto/rpctransact_grpc_pb' ;
9
- import { callTx } from './contracts/call' ;
10
+ import { ResultStatus } from '../proto/rpc_pb' ;
11
+ import { ContractCodec , getContractCodec } from './codec' ;
12
+ import { Address } from './contracts/abi' ;
13
+ import { makeCallTx } from './contracts/call' ;
10
14
import { CallOptions , Contract , ContractInstance } from './contracts/contract' ;
11
15
import { toBuffer } from './convert' ;
12
16
import { getException } from './error' ;
13
17
import { EventCallback , Events , EventStream , latestStreamingBlockRange } from './events' ;
14
18
import { Namereg } from './namereg' ;
19
+ import { Provider } from './solts/provider.gd' ;
15
20
16
21
type TxCallback = ( error : grpc . ServiceError | null , txe : TxExecution ) => void ;
17
22
18
23
export type Pipe = ( payload : CallTx , callback : TxCallback ) => void ;
19
24
20
- export class Burrow {
25
+ export type Interceptor = ( result : TxExecution ) => Promise < TxExecution > ;
26
+
27
+ export class Client implements Provider {
28
+ interceptor : Interceptor ;
21
29
readonly events : Events ;
22
30
readonly namereg : Namereg ;
23
31
@@ -33,14 +41,15 @@ export class Burrow {
33
41
this . executionEvents = new ExecutionEventsClient ( url , credentials ) ;
34
42
this . transact = new TransactClient ( url , credentials ) ;
35
43
this . query = new QueryClient ( url , credentials ) ;
36
-
37
- this . callPipe = this . transact . callTxSync . bind ( this . transact ) ;
38
- this . simPipe = this . transact . callTxSim . bind ( this . transact ) ;
39
-
40
44
// This is the execution events streaming service running on top of the raw streaming function.
41
45
this . events = new Events ( this . executionEvents ) ;
42
46
// Contracts stuff running on top of grpc
43
47
this . namereg = new Namereg ( this . transact , this . query , this . account ) ;
48
+ // NOTE: in general interceptor may be async
49
+ this . interceptor = async ( data ) => data ;
50
+
51
+ this . callPipe = this . transact . callTxSync . bind ( this . transact ) ;
52
+ this . simPipe = this . transact . callTxSim . bind ( this . transact ) ;
44
53
}
45
54
46
55
/**
@@ -76,24 +85,24 @@ export class Burrow {
76
85
) ;
77
86
}
78
87
79
- call ( callTx : CallTx ) : Promise < TxExecution > {
88
+ callTxSync ( callTx : CallTx ) : Promise < TxExecution > {
80
89
return new Promise ( ( resolve , reject ) =>
81
- this . callPipe ( callTx , ( error , txe ) => {
90
+ this . transact . callTxSync ( callTx , ( error , txe ) => {
82
91
if ( error ) {
83
92
return reject ( error ) ;
84
93
}
85
94
const err = getException ( txe ) ;
86
95
if ( err ) {
87
96
return reject ( err ) ;
88
97
}
89
- return resolve ( txe ) ;
98
+ return resolve ( this . interceptor ( txe ) ) ;
90
99
} ) ,
91
100
) ;
92
101
}
93
102
94
- callSim ( callTx : CallTx ) : Promise < TxExecution > {
103
+ callTxSim ( callTx : CallTx ) : Promise < TxExecution > {
95
104
return new Promise ( ( resolve , reject ) =>
96
- this . simPipe ( callTx , ( error , txe ) => {
105
+ this . transact . callTxSim ( callTx , ( error , txe ) => {
97
106
if ( error ) {
98
107
return reject ( error ) ;
99
108
}
@@ -106,6 +115,39 @@ export class Burrow {
106
115
) ;
107
116
}
108
117
118
+ status ( ) : Promise < ResultStatus > {
119
+ return new Promise ( ( resolve , reject ) =>
120
+ this . query . status ( new StatusParam ( ) , ( err , resp ) => ( err ? reject ( err ) : resolve ( resp ) ) ) ,
121
+ ) ;
122
+ }
123
+
124
+ async latestHeight ( ) : Promise < number > {
125
+ const status = await this . status ( ) ;
126
+ return status . getSyncinfo ( ) ?. getLatestblockheight ( ) ?? 0 ;
127
+ }
128
+
129
+ // Methods below implement the generated codegen provider
130
+ // TODO: should probably generate canonical version of Provider interface somewhere outside of files
131
+
132
+ async deploy ( msg : CallTx ) : Promise < Address > {
133
+ const txe = await this . callTxSync ( msg ) ;
134
+ const contractAddress = txe . getReceipt ( ) ?. getContractaddress_asU8 ( ) ;
135
+ if ( ! contractAddress ) {
136
+ throw new Error ( `deploy appears to have succeeded but contract address is missing from result: ${ txe } ` ) ;
137
+ }
138
+ return Buffer . from ( contractAddress ) . toString ( 'hex' ) . toUpperCase ( ) ;
139
+ }
140
+
141
+ async call ( msg : CallTx ) : Promise < Uint8Array | undefined > {
142
+ const txe = await this . callTxSync ( msg ) ;
143
+ return txe . getResult ( ) ?. getReturn_asU8 ( ) ;
144
+ }
145
+
146
+ async callSim ( msg : CallTx ) : Promise < Uint8Array | undefined > {
147
+ const txe = await this . callTxSim ( msg ) ;
148
+ return txe . getResult ( ) ?. getReturn_asU8 ( ) ;
149
+ }
150
+
109
151
listen (
110
152
signature : string ,
111
153
address : string ,
@@ -115,7 +157,12 @@ export class Burrow {
115
157
return this . events . listen ( range , address , signature , callback ) ;
116
158
}
117
159
118
- callTx ( data : string | Uint8Array , address ?: string , contractMeta : ContractMeta [ ] = [ ] ) : CallTx {
119
- return callTx ( typeof data === 'string' ? toBuffer ( data ) : data , this . account , address , contractMeta ) ;
160
+ payload ( data : string | Uint8Array , address ?: string , contractMeta : ContractMeta [ ] = [ ] ) : CallTx {
161
+ return makeCallTx ( typeof data === 'string' ? toBuffer ( data ) : data , this . account , address , contractMeta ) ;
162
+ }
163
+
164
+ contractCodec ( contractABI : string ) : ContractCodec {
165
+ const iface = new Interface ( contractABI ) ;
166
+ return getContractCodec ( iface ) ;
120
167
}
121
168
}
0 commit comments