@0xsequence/guard 0.43.34 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,9 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var ethers = require('ethers');
6
+ var core = require('@0xsequence/core');
7
+
5
8
  function _extends() {
6
9
  _extends = Object.assign ? Object.assign.bind() : function (target) {
7
10
  for (var i = 1; i < arguments.length; i++) {
@@ -18,7 +21,7 @@ function _extends() {
18
21
  }
19
22
 
20
23
  /* eslint-disable */
21
- // sequence-guard v0.4.0 98e0726794b2b5922a0e356280daac3a409602e4
24
+ // sequence-guard v0.4.0 a29651d1d5f63268e8d03b51e46557e0632c144d
22
25
  // --
23
26
  // Code generated by webrpc-gen@v0.10.x-dev with typescript generator. DO NOT EDIT.
24
27
  //
@@ -31,19 +34,16 @@ const WebRPCVersion = "v1";
31
34
  const WebRPCSchemaVersion = "v0.4.0";
32
35
 
33
36
  // Schema hash generated from your RIDL schema
34
- const WebRPCSchemaHash = "98e0726794b2b5922a0e356280daac3a409602e4";
37
+ const WebRPCSchemaHash = "a29651d1d5f63268e8d03b51e46557e0632c144d";
35
38
 
36
39
  //
37
40
  // Types
38
41
  //
39
-
40
42
  //
41
43
  // Client
42
44
  //
43
45
  class Guard {
44
46
  constructor(hostname, fetch) {
45
- this.hostname = void 0;
46
- this.fetch = void 0;
47
47
  this.path = '/rpc/Guard/';
48
48
  this.ping = headers => {
49
49
  return this.fetch(this.url('Ping'), createHTTPRequest({}, headers)).then(res => {
@@ -72,26 +72,26 @@ class Guard {
72
72
  });
73
73
  });
74
74
  };
75
- this.getSequenceContext = headers => {
76
- return this.fetch(this.url('GetSequenceContext'), createHTTPRequest({}, headers)).then(res => {
75
+ this.getSignerConfig = (args, headers) => {
76
+ return this.fetch(this.url('GetSignerConfig'), createHTTPRequest(args, headers)).then(res => {
77
77
  return buildResponse(res).then(_data => {
78
78
  return {
79
- data: _data.data
79
+ signerConfig: _data.signerConfig
80
80
  };
81
81
  });
82
82
  });
83
83
  };
84
- this.getSignerConfig = headers => {
85
- return this.fetch(this.url('GetSignerConfig'), createHTTPRequest({}, headers)).then(res => {
84
+ this.sign = (args, headers) => {
85
+ return this.fetch(this.url('Sign'), createHTTPRequest(args, headers)).then(res => {
86
86
  return buildResponse(res).then(_data => {
87
87
  return {
88
- signerConfig: _data.signerConfig
88
+ sig: _data.sig
89
89
  };
90
90
  });
91
91
  });
92
92
  };
93
- this.sign = (args, headers) => {
94
- return this.fetch(this.url('Sign'), createHTTPRequest(args, headers)).then(res => {
93
+ this.signWith = (args, headers) => {
94
+ return this.fetch(this.url('SignWith'), createHTTPRequest(args, headers)).then(res => {
95
95
  return buildResponse(res).then(_data => {
96
96
  return {
97
97
  sig: _data.sig
@@ -135,7 +135,84 @@ const buildResponse = res => {
135
135
  });
136
136
  };
137
137
 
138
+ class GuardSigner {
139
+ constructor(address, url, appendSuffix = false) {
140
+ this.requests = new Map();
141
+ this.address = address;
142
+ this.url = url;
143
+ this.appendSuffix = appendSuffix;
144
+ this.guard = new Guard(url, global.fetch);
145
+ }
146
+ async getAddress() {
147
+ return this.address;
148
+ }
149
+ async requestSignature(id, _message, metadata, callbacks) {
150
+ if (!core.commons.isWalletSignRequestMetadata(metadata)) {
151
+ callbacks.onRejection('Expected Sequence-like metadata');
152
+ } else {
153
+ // Queue the request first, this method only does that
154
+ // the requesting to the API is later handled on every status change
155
+ this.requests.set(id, callbacks);
156
+ }
157
+ return true;
158
+ }
159
+ notifyStatusChange(id, status, metadata) {
160
+ if (!this.requests.has(id)) return;
161
+ if (!core.commons.isWalletSignRequestMetadata(metadata)) {
162
+ this.requests.get(id).onRejection('Expected Sequence-like metadata (status update)');
163
+ return;
164
+ }
165
+ this.evaluateRequest(id, status.message, status, metadata);
166
+ }
167
+ packMsgAndSig(address, msg, sig, chainId) {
168
+ return ethers.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
169
+ }
170
+ keyOfRequest(signer, msg, auxData, chainId) {
171
+ return ethers.ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData]);
172
+ }
173
+ async evaluateRequest(id, message, _, metadata) {
174
+ var _metadata$parts;
175
+ // Building auxData, notice: this uses the old v1 format
176
+ // TODO: We should update the guard API so we can pass the metadata directly
177
+ const coder = core.universal.genericCoderFor(metadata.config.version);
178
+ const {
179
+ encoded
180
+ } = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
181
+ try {
182
+ var _this$requests$get;
183
+ const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId);
184
+ const lastAttempt = (_this$requests$get = this.requests.get(id)) == null ? void 0 : _this$requests$get.lastAttempt;
185
+ if (lastAttempt === key) {
186
+ return;
187
+ }
188
+ this.requests.get(id).lastAttempt = key;
189
+ const result = await this.guard.signWith({
190
+ signer: this.address,
191
+ request: {
192
+ msg: ethers.ethers.utils.hexlify(message),
193
+ auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
194
+ chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
195
+ }
196
+ });
197
+
198
+ if (ethers.ethers.utils.arrayify(result.sig).length !== 0) {
199
+ this.requests.get(id).onSignature(result.sig);
200
+ this.requests.delete(id);
201
+ }
202
+ } catch (e) {
203
+ // The guard signer may reject the request for a number of reasons
204
+ // like for example, if it's being the first signer (it waits for other signers to sign first)
205
+ // for now we ignore all errors, but we should probably handle them
206
+ // TODO: Filter real errors from control flow errors
207
+ }
208
+ }
209
+ suffix() {
210
+ return this.appendSuffix ? [3] : [];
211
+ }
212
+ }
213
+
138
214
  exports.Guard = Guard;
215
+ exports.GuardSigner = GuardSigner;
139
216
  exports.WebRPCSchemaHash = WebRPCSchemaHash;
140
217
  exports.WebRPCSchemaVersion = WebRPCSchemaVersion;
141
218
  exports.WebRPCVersion = WebRPCVersion;
@@ -2,6 +2,9 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var ethers = require('ethers');
6
+ var core = require('@0xsequence/core');
7
+
5
8
  function _extends() {
6
9
  _extends = Object.assign ? Object.assign.bind() : function (target) {
7
10
  for (var i = 1; i < arguments.length; i++) {
@@ -18,7 +21,7 @@ function _extends() {
18
21
  }
19
22
 
20
23
  /* eslint-disable */
21
- // sequence-guard v0.4.0 98e0726794b2b5922a0e356280daac3a409602e4
24
+ // sequence-guard v0.4.0 a29651d1d5f63268e8d03b51e46557e0632c144d
22
25
  // --
23
26
  // Code generated by webrpc-gen@v0.10.x-dev with typescript generator. DO NOT EDIT.
24
27
  //
@@ -31,19 +34,16 @@ const WebRPCVersion = "v1";
31
34
  const WebRPCSchemaVersion = "v0.4.0";
32
35
 
33
36
  // Schema hash generated from your RIDL schema
34
- const WebRPCSchemaHash = "98e0726794b2b5922a0e356280daac3a409602e4";
37
+ const WebRPCSchemaHash = "a29651d1d5f63268e8d03b51e46557e0632c144d";
35
38
 
36
39
  //
37
40
  // Types
38
41
  //
39
-
40
42
  //
41
43
  // Client
42
44
  //
43
45
  class Guard {
44
46
  constructor(hostname, fetch) {
45
- this.hostname = void 0;
46
- this.fetch = void 0;
47
47
  this.path = '/rpc/Guard/';
48
48
  this.ping = headers => {
49
49
  return this.fetch(this.url('Ping'), createHTTPRequest({}, headers)).then(res => {
@@ -72,26 +72,26 @@ class Guard {
72
72
  });
73
73
  });
74
74
  };
75
- this.getSequenceContext = headers => {
76
- return this.fetch(this.url('GetSequenceContext'), createHTTPRequest({}, headers)).then(res => {
75
+ this.getSignerConfig = (args, headers) => {
76
+ return this.fetch(this.url('GetSignerConfig'), createHTTPRequest(args, headers)).then(res => {
77
77
  return buildResponse(res).then(_data => {
78
78
  return {
79
- data: _data.data
79
+ signerConfig: _data.signerConfig
80
80
  };
81
81
  });
82
82
  });
83
83
  };
84
- this.getSignerConfig = headers => {
85
- return this.fetch(this.url('GetSignerConfig'), createHTTPRequest({}, headers)).then(res => {
84
+ this.sign = (args, headers) => {
85
+ return this.fetch(this.url('Sign'), createHTTPRequest(args, headers)).then(res => {
86
86
  return buildResponse(res).then(_data => {
87
87
  return {
88
- signerConfig: _data.signerConfig
88
+ sig: _data.sig
89
89
  };
90
90
  });
91
91
  });
92
92
  };
93
- this.sign = (args, headers) => {
94
- return this.fetch(this.url('Sign'), createHTTPRequest(args, headers)).then(res => {
93
+ this.signWith = (args, headers) => {
94
+ return this.fetch(this.url('SignWith'), createHTTPRequest(args, headers)).then(res => {
95
95
  return buildResponse(res).then(_data => {
96
96
  return {
97
97
  sig: _data.sig
@@ -135,7 +135,84 @@ const buildResponse = res => {
135
135
  });
136
136
  };
137
137
 
138
+ class GuardSigner {
139
+ constructor(address, url, appendSuffix = false) {
140
+ this.requests = new Map();
141
+ this.address = address;
142
+ this.url = url;
143
+ this.appendSuffix = appendSuffix;
144
+ this.guard = new Guard(url, global.fetch);
145
+ }
146
+ async getAddress() {
147
+ return this.address;
148
+ }
149
+ async requestSignature(id, _message, metadata, callbacks) {
150
+ if (!core.commons.isWalletSignRequestMetadata(metadata)) {
151
+ callbacks.onRejection('Expected Sequence-like metadata');
152
+ } else {
153
+ // Queue the request first, this method only does that
154
+ // the requesting to the API is later handled on every status change
155
+ this.requests.set(id, callbacks);
156
+ }
157
+ return true;
158
+ }
159
+ notifyStatusChange(id, status, metadata) {
160
+ if (!this.requests.has(id)) return;
161
+ if (!core.commons.isWalletSignRequestMetadata(metadata)) {
162
+ this.requests.get(id).onRejection('Expected Sequence-like metadata (status update)');
163
+ return;
164
+ }
165
+ this.evaluateRequest(id, status.message, status, metadata);
166
+ }
167
+ packMsgAndSig(address, msg, sig, chainId) {
168
+ return ethers.ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
169
+ }
170
+ keyOfRequest(signer, msg, auxData, chainId) {
171
+ return ethers.ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData]);
172
+ }
173
+ async evaluateRequest(id, message, _, metadata) {
174
+ var _metadata$parts;
175
+ // Building auxData, notice: this uses the old v1 format
176
+ // TODO: We should update the guard API so we can pass the metadata directly
177
+ const coder = core.universal.genericCoderFor(metadata.config.version);
178
+ const {
179
+ encoded
180
+ } = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
181
+ try {
182
+ var _this$requests$get;
183
+ const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId);
184
+ const lastAttempt = (_this$requests$get = this.requests.get(id)) == null ? void 0 : _this$requests$get.lastAttempt;
185
+ if (lastAttempt === key) {
186
+ return;
187
+ }
188
+ this.requests.get(id).lastAttempt = key;
189
+ const result = await this.guard.signWith({
190
+ signer: this.address,
191
+ request: {
192
+ msg: ethers.ethers.utils.hexlify(message),
193
+ auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
194
+ chainId: ethers.ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
195
+ }
196
+ });
197
+
198
+ if (ethers.ethers.utils.arrayify(result.sig).length !== 0) {
199
+ this.requests.get(id).onSignature(result.sig);
200
+ this.requests.delete(id);
201
+ }
202
+ } catch (e) {
203
+ // The guard signer may reject the request for a number of reasons
204
+ // like for example, if it's being the first signer (it waits for other signers to sign first)
205
+ // for now we ignore all errors, but we should probably handle them
206
+ // TODO: Filter real errors from control flow errors
207
+ }
208
+ }
209
+ suffix() {
210
+ return this.appendSuffix ? [3] : [];
211
+ }
212
+ }
213
+
138
214
  exports.Guard = Guard;
215
+ exports.GuardSigner = GuardSigner;
139
216
  exports.WebRPCSchemaHash = WebRPCSchemaHash;
140
217
  exports.WebRPCSchemaVersion = WebRPCSchemaVersion;
141
218
  exports.WebRPCVersion = WebRPCVersion;
@@ -1,3 +1,6 @@
1
+ import { ethers } from 'ethers';
2
+ import { commons, universal } from '@0xsequence/core';
3
+
1
4
  function _extends() {
2
5
  _extends = Object.assign ? Object.assign.bind() : function (target) {
3
6
  for (var i = 1; i < arguments.length; i++) {
@@ -14,7 +17,7 @@ function _extends() {
14
17
  }
15
18
 
16
19
  /* eslint-disable */
17
- // sequence-guard v0.4.0 98e0726794b2b5922a0e356280daac3a409602e4
20
+ // sequence-guard v0.4.0 a29651d1d5f63268e8d03b51e46557e0632c144d
18
21
  // --
19
22
  // Code generated by webrpc-gen@v0.10.x-dev with typescript generator. DO NOT EDIT.
20
23
  //
@@ -27,19 +30,16 @@ const WebRPCVersion = "v1";
27
30
  const WebRPCSchemaVersion = "v0.4.0";
28
31
 
29
32
  // Schema hash generated from your RIDL schema
30
- const WebRPCSchemaHash = "98e0726794b2b5922a0e356280daac3a409602e4";
33
+ const WebRPCSchemaHash = "a29651d1d5f63268e8d03b51e46557e0632c144d";
31
34
 
32
35
  //
33
36
  // Types
34
37
  //
35
-
36
38
  //
37
39
  // Client
38
40
  //
39
41
  class Guard {
40
42
  constructor(hostname, fetch) {
41
- this.hostname = void 0;
42
- this.fetch = void 0;
43
43
  this.path = '/rpc/Guard/';
44
44
  this.ping = headers => {
45
45
  return this.fetch(this.url('Ping'), createHTTPRequest({}, headers)).then(res => {
@@ -68,26 +68,26 @@ class Guard {
68
68
  });
69
69
  });
70
70
  };
71
- this.getSequenceContext = headers => {
72
- return this.fetch(this.url('GetSequenceContext'), createHTTPRequest({}, headers)).then(res => {
71
+ this.getSignerConfig = (args, headers) => {
72
+ return this.fetch(this.url('GetSignerConfig'), createHTTPRequest(args, headers)).then(res => {
73
73
  return buildResponse(res).then(_data => {
74
74
  return {
75
- data: _data.data
75
+ signerConfig: _data.signerConfig
76
76
  };
77
77
  });
78
78
  });
79
79
  };
80
- this.getSignerConfig = headers => {
81
- return this.fetch(this.url('GetSignerConfig'), createHTTPRequest({}, headers)).then(res => {
80
+ this.sign = (args, headers) => {
81
+ return this.fetch(this.url('Sign'), createHTTPRequest(args, headers)).then(res => {
82
82
  return buildResponse(res).then(_data => {
83
83
  return {
84
- signerConfig: _data.signerConfig
84
+ sig: _data.sig
85
85
  };
86
86
  });
87
87
  });
88
88
  };
89
- this.sign = (args, headers) => {
90
- return this.fetch(this.url('Sign'), createHTTPRequest(args, headers)).then(res => {
89
+ this.signWith = (args, headers) => {
90
+ return this.fetch(this.url('SignWith'), createHTTPRequest(args, headers)).then(res => {
91
91
  return buildResponse(res).then(_data => {
92
92
  return {
93
93
  sig: _data.sig
@@ -131,4 +131,80 @@ const buildResponse = res => {
131
131
  });
132
132
  };
133
133
 
134
- export { Guard, WebRPCSchemaHash, WebRPCSchemaVersion, WebRPCVersion };
134
+ class GuardSigner {
135
+ constructor(address, url, appendSuffix = false) {
136
+ this.requests = new Map();
137
+ this.address = address;
138
+ this.url = url;
139
+ this.appendSuffix = appendSuffix;
140
+ this.guard = new Guard(url, global.fetch);
141
+ }
142
+ async getAddress() {
143
+ return this.address;
144
+ }
145
+ async requestSignature(id, _message, metadata, callbacks) {
146
+ if (!commons.isWalletSignRequestMetadata(metadata)) {
147
+ callbacks.onRejection('Expected Sequence-like metadata');
148
+ } else {
149
+ // Queue the request first, this method only does that
150
+ // the requesting to the API is later handled on every status change
151
+ this.requests.set(id, callbacks);
152
+ }
153
+ return true;
154
+ }
155
+ notifyStatusChange(id, status, metadata) {
156
+ if (!this.requests.has(id)) return;
157
+ if (!commons.isWalletSignRequestMetadata(metadata)) {
158
+ this.requests.get(id).onRejection('Expected Sequence-like metadata (status update)');
159
+ return;
160
+ }
161
+ this.evaluateRequest(id, status.message, status, metadata);
162
+ }
163
+ packMsgAndSig(address, msg, sig, chainId) {
164
+ return ethers.utils.defaultAbiCoder.encode(['address', 'uint256', 'bytes', 'bytes'], [address, chainId, msg, sig]);
165
+ }
166
+ keyOfRequest(signer, msg, auxData, chainId) {
167
+ return ethers.utils.solidityKeccak256(['address', 'uint256', 'bytes', 'bytes'], [signer, chainId, msg, auxData]);
168
+ }
169
+ async evaluateRequest(id, message, _, metadata) {
170
+ var _metadata$parts;
171
+ // Building auxData, notice: this uses the old v1 format
172
+ // TODO: We should update the guard API so we can pass the metadata directly
173
+ const coder = universal.genericCoderFor(metadata.config.version);
174
+ const {
175
+ encoded
176
+ } = coder.signature.encodeSigners(metadata.config, (_metadata$parts = metadata.parts) != null ? _metadata$parts : new Map(), [], metadata.chainId);
177
+ try {
178
+ var _this$requests$get;
179
+ const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId);
180
+ const lastAttempt = (_this$requests$get = this.requests.get(id)) == null ? void 0 : _this$requests$get.lastAttempt;
181
+ if (lastAttempt === key) {
182
+ return;
183
+ }
184
+ this.requests.get(id).lastAttempt = key;
185
+ const result = await this.guard.signWith({
186
+ signer: this.address,
187
+ request: {
188
+ msg: ethers.utils.hexlify(message),
189
+ auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
190
+ chainId: ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
191
+ }
192
+ });
193
+
194
+ if (ethers.utils.arrayify(result.sig).length !== 0) {
195
+ this.requests.get(id).onSignature(result.sig);
196
+ this.requests.delete(id);
197
+ }
198
+ } catch (e) {
199
+ // The guard signer may reject the request for a number of reasons
200
+ // like for example, if it's being the first signer (it waits for other signers to sign first)
201
+ // for now we ignore all errors, but we should probably handle them
202
+ // TODO: Filter real errors from control flow errors
203
+ }
204
+ }
205
+ suffix() {
206
+ return this.appendSuffix ? [3] : [];
207
+ }
208
+ }
209
+
210
+ export { Guard, GuardSigner, WebRPCSchemaHash, WebRPCSchemaVersion, WebRPCVersion };
@@ -1,6 +1,6 @@
1
1
  export declare const WebRPCVersion = "v1";
2
2
  export declare const WebRPCSchemaVersion = "v0.4.0";
3
- export declare const WebRPCSchemaHash = "98e0726794b2b5922a0e356280daac3a409602e4";
3
+ export declare const WebRPCSchemaHash = "a29651d1d5f63268e8d03b51e46557e0632c144d";
4
4
  export interface Version {
5
5
  webrpcVersion: string;
6
6
  schemaVersion: string;
@@ -15,17 +15,9 @@ export interface RuntimeStatus {
15
15
  branch: string;
16
16
  commitHash: string;
17
17
  }
18
- export interface SequenceContext {
19
- factory: string;
20
- mainModule: string;
21
- mainModuleUpgradable: string;
22
- guestModule: string;
23
- utils: string;
24
- }
25
18
  export interface WalletConfig {
26
19
  address: string;
27
- signers: Array<WalletSigner>;
28
- threshold: number;
20
+ content: string;
29
21
  }
30
22
  export interface WalletSigner {
31
23
  address: string;
@@ -40,9 +32,9 @@ export interface Guard {
40
32
  ping(headers?: object): Promise<PingReturn>;
41
33
  version(headers?: object): Promise<VersionReturn>;
42
34
  runtimeStatus(headers?: object): Promise<RuntimeStatusReturn>;
43
- getSequenceContext(headers?: object): Promise<GetSequenceContextReturn>;
44
- getSignerConfig(headers?: object): Promise<GetSignerConfigReturn>;
35
+ getSignerConfig(args: GetSignerConfigArgs, headers?: object): Promise<GetSignerConfigReturn>;
45
36
  sign(args: SignArgs, headers?: object): Promise<SignReturn>;
37
+ signWith(args: SignWithArgs, headers?: object): Promise<SignWithReturn>;
46
38
  }
47
39
  export interface PingArgs {
48
40
  }
@@ -59,12 +51,8 @@ export interface RuntimeStatusArgs {
59
51
  export interface RuntimeStatusReturn {
60
52
  status: RuntimeStatus;
61
53
  }
62
- export interface GetSequenceContextArgs {
63
- }
64
- export interface GetSequenceContextReturn {
65
- data: SequenceContext;
66
- }
67
54
  export interface GetSignerConfigArgs {
55
+ signer: string;
68
56
  }
69
57
  export interface GetSignerConfigReturn {
70
58
  signerConfig: WalletConfig;
@@ -75,6 +63,13 @@ export interface SignArgs {
75
63
  export interface SignReturn {
76
64
  sig: string;
77
65
  }
66
+ export interface SignWithArgs {
67
+ signer: string;
68
+ request: SignRequest;
69
+ }
70
+ export interface SignWithReturn {
71
+ sig: string;
72
+ }
78
73
  export declare class Guard implements Guard {
79
74
  protected hostname: string;
80
75
  protected fetch: Fetch;
@@ -84,9 +79,9 @@ export declare class Guard implements Guard {
84
79
  ping: (headers?: object | undefined) => Promise<PingReturn>;
85
80
  version: (headers?: object | undefined) => Promise<VersionReturn>;
86
81
  runtimeStatus: (headers?: object | undefined) => Promise<RuntimeStatusReturn>;
87
- getSequenceContext: (headers?: object | undefined) => Promise<GetSequenceContextReturn>;
88
- getSignerConfig: (headers?: object | undefined) => Promise<GetSignerConfigReturn>;
82
+ getSignerConfig: (args: GetSignerConfigArgs, headers?: object | undefined) => Promise<GetSignerConfigReturn>;
89
83
  sign: (args: SignArgs, headers?: object | undefined) => Promise<SignReturn>;
84
+ signWith: (args: SignWithArgs, headers?: object | undefined) => Promise<SignWithReturn>;
90
85
  }
91
86
  export interface WebRPCError extends Error {
92
87
  code: string;
@@ -1 +1,2 @@
1
1
  export * from './guard.gen';
2
+ export * from './signer';
@@ -0,0 +1,21 @@
1
+ import { signers, Status } from '@0xsequence/signhub';
2
+ import { BytesLike } from 'ethers';
3
+ export declare class GuardSigner implements signers.SapientSigner {
4
+ readonly address: string;
5
+ readonly url: string;
6
+ readonly appendSuffix: boolean;
7
+ private guard;
8
+ private requests;
9
+ constructor(address: string, url: string, appendSuffix?: boolean);
10
+ getAddress(): Promise<string>;
11
+ requestSignature(id: string, _message: BytesLike, metadata: Object, callbacks: {
12
+ onSignature: (signature: BytesLike) => void;
13
+ onRejection: (error: string) => void;
14
+ onStatus: (situation: string) => void;
15
+ }): Promise<boolean>;
16
+ notifyStatusChange(id: string, status: Status, metadata: Object): void;
17
+ private packMsgAndSig;
18
+ private keyOfRequest;
19
+ private evaluateRequest;
20
+ suffix(): BytesLike;
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xsequence/guard",
3
- "version": "0.43.34",
3
+ "version": "1.0.1",
4
4
  "description": "guard sub-package for Sequence",
5
5
  "repository": "https://github.com/0xsequence/sequence.js/tree/master/packages/guard",
6
6
  "source": "src/index.ts",
@@ -8,9 +8,11 @@
8
8
  "module": "dist/0xsequence-guard.esm.js",
9
9
  "author": "Horizon Blockchain Games",
10
10
  "license": "Apache-2.0",
11
- "dependencies": {},
12
- "peerDependencies": {},
13
- "devDependencies": {},
11
+ "dependencies": {
12
+ "ethers": "^5.7.2",
13
+ "@0xsequence/core": "1.0.1",
14
+ "@0xsequence/signhub": "1.0.1"
15
+ },
14
16
  "files": [
15
17
  "src",
16
18
  "dist"
package/src/guard.gen.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable */
2
- // sequence-guard v0.4.0 98e0726794b2b5922a0e356280daac3a409602e4
2
+ // sequence-guard v0.4.0 a29651d1d5f63268e8d03b51e46557e0632c144d
3
3
  // --
4
4
  // Code generated by webrpc-gen@v0.10.x-dev with typescript generator. DO NOT EDIT.
5
5
  //
@@ -12,7 +12,7 @@ export const WebRPCVersion = "v1"
12
12
  export const WebRPCSchemaVersion = "v0.4.0"
13
13
 
14
14
  // Schema hash generated from your RIDL schema
15
- export const WebRPCSchemaHash = "98e0726794b2b5922a0e356280daac3a409602e4"
15
+ export const WebRPCSchemaHash = "a29651d1d5f63268e8d03b51e46557e0632c144d"
16
16
 
17
17
  //
18
18
  // Types
@@ -35,18 +35,9 @@ export interface RuntimeStatus {
35
35
  commitHash: string
36
36
  }
37
37
 
38
- export interface SequenceContext {
39
- factory: string
40
- mainModule: string
41
- mainModuleUpgradable: string
42
- guestModule: string
43
- utils: string
44
- }
45
-
46
38
  export interface WalletConfig {
47
39
  address: string
48
- signers: Array<WalletSigner>
49
- threshold: number
40
+ content: string
50
41
  }
51
42
 
52
43
  export interface WalletSigner {
@@ -64,9 +55,9 @@ export interface Guard {
64
55
  ping(headers?: object): Promise<PingReturn>
65
56
  version(headers?: object): Promise<VersionReturn>
66
57
  runtimeStatus(headers?: object): Promise<RuntimeStatusReturn>
67
- getSequenceContext(headers?: object): Promise<GetSequenceContextReturn>
68
- getSignerConfig(headers?: object): Promise<GetSignerConfigReturn>
58
+ getSignerConfig(args: GetSignerConfigArgs, headers?: object): Promise<GetSignerConfigReturn>
69
59
  sign(args: SignArgs, headers?: object): Promise<SignReturn>
60
+ signWith(args: SignWithArgs, headers?: object): Promise<SignWithReturn>
70
61
  }
71
62
 
72
63
  export interface PingArgs {
@@ -87,13 +78,8 @@ export interface RuntimeStatusArgs {
87
78
  export interface RuntimeStatusReturn {
88
79
  status: RuntimeStatus
89
80
  }
90
- export interface GetSequenceContextArgs {
91
- }
92
-
93
- export interface GetSequenceContextReturn {
94
- data: SequenceContext
95
- }
96
81
  export interface GetSignerConfigArgs {
82
+ signer: string
97
83
  }
98
84
 
99
85
  export interface GetSignerConfigReturn {
@@ -106,6 +92,14 @@ export interface SignArgs {
106
92
  export interface SignReturn {
107
93
  sig: string
108
94
  }
95
+ export interface SignWithArgs {
96
+ signer: string
97
+ request: SignRequest
98
+ }
99
+
100
+ export interface SignWithReturn {
101
+ sig: string
102
+ }
109
103
 
110
104
 
111
105
 
@@ -165,35 +159,33 @@ export class Guard implements Guard {
165
159
  })
166
160
  }
167
161
 
168
- getSequenceContext = (headers?: object): Promise<GetSequenceContextReturn> => {
162
+ getSignerConfig = (args: GetSignerConfigArgs, headers?: object): Promise<GetSignerConfigReturn> => {
169
163
  return this.fetch(
170
- this.url('GetSequenceContext'),
171
- createHTTPRequest({}, headers)
172
- ).then((res) => {
164
+ this.url('GetSignerConfig'),
165
+ createHTTPRequest(args, headers)).then((res) => {
173
166
  return buildResponse(res).then(_data => {
174
167
  return {
175
- data: <SequenceContext>(_data.data)
168
+ signerConfig: <WalletConfig>(_data.signerConfig)
176
169
  }
177
170
  })
178
171
  })
179
172
  }
180
173
 
181
- getSignerConfig = (headers?: object): Promise<GetSignerConfigReturn> => {
174
+ sign = (args: SignArgs, headers?: object): Promise<SignReturn> => {
182
175
  return this.fetch(
183
- this.url('GetSignerConfig'),
184
- createHTTPRequest({}, headers)
185
- ).then((res) => {
176
+ this.url('Sign'),
177
+ createHTTPRequest(args, headers)).then((res) => {
186
178
  return buildResponse(res).then(_data => {
187
179
  return {
188
- signerConfig: <WalletConfig>(_data.signerConfig)
180
+ sig: <string>(_data.sig)
189
181
  }
190
182
  })
191
183
  })
192
184
  }
193
185
 
194
- sign = (args: SignArgs, headers?: object): Promise<SignReturn> => {
186
+ signWith = (args: SignWithArgs, headers?: object): Promise<SignWithReturn> => {
195
187
  return this.fetch(
196
- this.url('Sign'),
188
+ this.url('SignWith'),
197
189
  createHTTPRequest(args, headers)).then((res) => {
198
190
  return buildResponse(res).then(_data => {
199
191
  return {
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './guard.gen'
2
+ export * from './signer'
package/src/signer.ts ADDED
@@ -0,0 +1,117 @@
1
+
2
+ import { signers, Status } from '@0xsequence/signhub'
3
+ import { BytesLike, ethers } from 'ethers'
4
+ import { Guard } from './guard.gen'
5
+ import { commons, universal } from '@0xsequence/core'
6
+
7
+ export class GuardSigner implements signers.SapientSigner {
8
+ private guard: Guard
9
+ private requests: Map<string, {
10
+ lastAttempt?: string;
11
+ onSignature: (signature: BytesLike) => void;
12
+ onRejection: (error: string) => void;
13
+ onStatus: (situation: string) => void;
14
+ }> = new Map()
15
+
16
+ constructor(
17
+ public readonly address: string,
18
+ public readonly url: string,
19
+ public readonly appendSuffix: boolean = false
20
+ ) {
21
+ this.guard = new Guard(url, global.fetch)
22
+ }
23
+
24
+ async getAddress(): Promise<string> {
25
+ return this.address
26
+ }
27
+
28
+ async requestSignature(
29
+ id: string,
30
+ _message: BytesLike,
31
+ metadata: Object,
32
+ callbacks: {
33
+ onSignature: (signature: BytesLike) => void;
34
+ onRejection: (error: string) => void;
35
+ onStatus: (situation: string) => void;
36
+ }
37
+ ): Promise<boolean> {
38
+ if (!commons.isWalletSignRequestMetadata(metadata)) {
39
+ callbacks.onRejection('Expected Sequence-like metadata')
40
+ } else {
41
+ // Queue the request first, this method only does that
42
+ // the requesting to the API is later handled on every status change
43
+ this.requests.set(id, callbacks)
44
+ }
45
+
46
+ return true
47
+ }
48
+
49
+ notifyStatusChange(
50
+ id: string,
51
+ status: Status,
52
+ metadata: Object
53
+ ): void {
54
+ if (!this.requests.has(id)) return
55
+
56
+ if (!commons.isWalletSignRequestMetadata(metadata)) {
57
+ this.requests.get(id)!.onRejection('Expected Sequence-like metadata (status update)')
58
+ return
59
+ }
60
+
61
+ this.evaluateRequest(id, status.message, status, metadata)
62
+ }
63
+
64
+ private packMsgAndSig(address: string, msg: BytesLike, sig: BytesLike, chainId: ethers.BigNumberish): string {
65
+ return ethers.utils.defaultAbiCoder.encode(
66
+ ['address', 'uint256', 'bytes', 'bytes'],
67
+ [address, chainId, msg, sig]
68
+ )
69
+ }
70
+
71
+ private keyOfRequest(signer: string, msg: BytesLike, auxData: BytesLike, chainId: ethers.BigNumberish): string {
72
+ return ethers.utils.solidityKeccak256(
73
+ ['address', 'uint256', 'bytes', 'bytes'],
74
+ [signer, chainId, msg, auxData]
75
+ )
76
+ }
77
+
78
+ private async evaluateRequest(id: string, message: BytesLike, _: Status, metadata: commons.WalletSignRequestMetadata): Promise<void> {
79
+ // Building auxData, notice: this uses the old v1 format
80
+ // TODO: We should update the guard API so we can pass the metadata directly
81
+ const coder = universal.genericCoderFor(metadata.config.version)
82
+ const { encoded } = coder.signature.encodeSigners(metadata.config, metadata.parts ?? new Map(), [], metadata.chainId)
83
+
84
+ try {
85
+ const key = this.keyOfRequest(this.address, message, encoded, metadata.chainId)
86
+ const lastAttempt = this.requests.get(id)?.lastAttempt
87
+ if (lastAttempt === key) {
88
+ return
89
+ }
90
+
91
+ this.requests.get(id)!.lastAttempt = key
92
+
93
+ const result = await this.guard.signWith({
94
+ signer: this.address,
95
+ request: {
96
+ msg: ethers.utils.hexlify(message),
97
+ auxData: this.packMsgAndSig(metadata.address, metadata.digest, encoded, metadata.chainId),
98
+ chainId: ethers.BigNumber.from(metadata.chainId).toNumber() // TODO: This should be a string (in the API)
99
+ }
100
+ })
101
+
102
+ if (ethers.utils.arrayify(result.sig).length !== 0) {
103
+ this.requests.get(id)!.onSignature(result.sig)
104
+ this.requests.delete(id)
105
+ }
106
+ } catch (e) {
107
+ // The guard signer may reject the request for a number of reasons
108
+ // like for example, if it's being the first signer (it waits for other signers to sign first)
109
+ // for now we ignore all errors, but we should probably handle them
110
+ // TODO: Filter real errors from control flow errors
111
+ }
112
+ }
113
+
114
+ suffix(): BytesLike {
115
+ return this.appendSuffix ? [ 3 ] : []
116
+ }
117
+ }