1
1
import 'dart:convert' ;
2
2
import 'dart:typed_data' ;
3
3
4
+ import 'package:typed_data/typed_data.dart' ;
5
+
4
6
import '../candid/idl.dart' ;
5
7
import '../principal/principal.dart' ;
6
8
import 'agent/api.dart' ;
9
+ import 'agent/http/types.dart' ;
7
10
import 'canisters/management.dart' ;
11
+ import 'cbor.dart' as cbor;
8
12
import 'errors.dart' ;
9
13
import 'polling/polling.dart' ;
10
14
import 'request_id.dart' ;
@@ -72,6 +76,7 @@ class CallConfig {
72
76
this .pollingStrategyFactory,
73
77
this .canisterId,
74
78
this .effectiveCanisterId,
79
+ this .callSync = true ,
75
80
});
76
81
77
82
factory CallConfig .fromJson (Map <String , dynamic > map) {
@@ -80,6 +85,7 @@ class CallConfig {
80
85
pollingStrategyFactory: map['pollingStrategyFactory' ],
81
86
canisterId: map['canisterId' ],
82
87
effectiveCanisterId: map['effectiveCanisterId' ],
88
+ callSync: map['callSync' ] ?? true ,
83
89
);
84
90
}
85
91
@@ -97,12 +103,16 @@ class CallConfig {
97
103
/// The effective canister ID. This should almost always be ignored.
98
104
final Principal ? effectiveCanisterId;
99
105
106
+ /// Whether to call the endpoint synchronously.
107
+ final bool callSync;
108
+
100
109
Map <String , dynamic > toJson () {
101
110
return {
102
111
'agent' : agent,
103
112
'pollingStrategyFactory' : pollingStrategyFactory,
104
113
'canisterId' : canisterId,
105
114
'effectiveCanisterId' : effectiveCanisterId,
115
+ 'callSync' : callSync,
106
116
};
107
117
}
108
118
}
@@ -114,6 +124,7 @@ class ActorConfig extends CallConfig {
114
124
super .pollingStrategyFactory,
115
125
super .canisterId,
116
126
super .effectiveCanisterId,
127
+ super .callSync,
117
128
this .callTransform,
118
129
this .queryTransform,
119
130
});
@@ -126,6 +137,7 @@ class ActorConfig extends CallConfig {
126
137
pollingStrategyFactory: map['pollingStrategyFactory' ],
127
138
canisterId: map['canisterId' ],
128
139
effectiveCanisterId: map['effectiveCanisterId' ],
140
+ callSync: map['callSync' ] ?? true ,
129
141
);
130
142
}
131
143
@@ -411,13 +423,15 @@ ActorMethod _createActorMethod(Actor actor, String methodName, Func func) {
411
423
final ecid = effectiveCanisterId != null
412
424
? Principal .from (effectiveCanisterId)
413
425
: cid;
414
- // final { requestId, response } =
415
- final result = await agent! .call (
426
+ final callSync = actor.metadata.config? .callSync ?? newOptions.callSync;
427
+
428
+ final result = await agent! .callRequest (
416
429
cid,
417
430
CallOptions (
418
431
methodName: methodName,
419
432
arg: arg,
420
433
effectiveCanisterId: ecid,
434
+ callSync: callSync,
421
435
),
422
436
null ,
423
437
);
@@ -428,13 +442,25 @@ ActorMethod _createActorMethod(Actor actor, String methodName, Func func) {
428
442
throw UpdateCallRejectedError (cid, methodName, result, requestId);
429
443
}
430
444
445
+ BinaryBlob ? certificate;
446
+ // Fall back to polling if we receive an "Accepted" response code,
447
+ // otherwise decode the certificate instantly.
448
+ if (result is CallResponseBody && result.response? .status != 202 ) {
449
+ final buffer = (result.response as HttpResponseBody ).arrayBuffer! ;
450
+ final decoded = cbor.cborDecode <Map >(buffer);
451
+ certificate = blobFromBuffer (
452
+ (decoded['certificate' ] as Uint8Buffer ).buffer,
453
+ );
454
+ }
455
+
431
456
final pollStrategy = pollingStrategyFactory ();
432
457
final responseBytes = await pollForResponse (
433
458
agent,
434
459
ecid,
435
460
requestId,
436
461
pollStrategy,
437
462
methodName,
463
+ overrideCertificate: certificate,
438
464
);
439
465
440
466
if (responseBytes.isNotEmpty) {
0 commit comments