@safe-global/relay-kit 1.1.0 → 1.3.0

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.
package/LICENSE.md CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Safe Ecosystem Foundation
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Safe Ecosystem Foundation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # Relay Kit
2
-
3
- [![NPM Version](https://badge.fury.io/js/%40safe-global%2Frelay-kit.svg)](https://badge.fury.io/js/%40safe-global%2Frelay-kit)
4
- [![GitHub Release](https://img.shields.io/github/release/safe-global/safe-core-sdk.svg?style=flat)](https://github.com/safe-global/safe-core-sdk/releases)
5
- [![GitHub](https://img.shields.io/github/license/safe-global/safe-core-sdk)](https://github.com/safe-global/safe-core-sdk/blob/main/LICENSE.md)
6
-
7
- The Relay Kit allows to abstract users from the transaction fees payment (gas fees) allowing the use of native token or ERC-20 tokens. This will enable you to pay transaction fees directly from funding available in a Safe.
8
-
9
- ## Reference
10
-
11
- - [Relay Kit docs](https://docs.safe.global/learn/safe-core-account-abstraction-sdk/relay-kit)
12
-
13
- ## License
14
-
15
- This library is [released under MIT](https://github.com/safe-global/safe-core-sdk/blob/main/LICENSE.md).
1
+ # Relay Kit
2
+
3
+ [![NPM Version](https://badge.fury.io/js/%40safe-global%2Frelay-kit.svg)](https://badge.fury.io/js/%40safe-global%2Frelay-kit)
4
+ [![GitHub Release](https://img.shields.io/github/release/safe-global/safe-core-sdk.svg?style=flat)](https://github.com/safe-global/safe-core-sdk/releases)
5
+ [![GitHub](https://img.shields.io/github/license/safe-global/safe-core-sdk)](https://github.com/safe-global/safe-core-sdk/blob/main/LICENSE.md)
6
+
7
+ The Relay Kit allows to abstract users from the transaction fees payment (gas fees) allowing the use of native token or ERC-20 tokens. This will enable you to pay transaction fees directly from funding available in a Safe.
8
+
9
+ ## Reference
10
+
11
+ - [Relay Kit docs](https://docs.safe.global/safe-core-aa-sdk/relay-kit)
12
+
13
+ ## License
14
+
15
+ This library is [released under MIT](https://github.com/safe-global/safe-core-sdk/blob/main/LICENSE.md).
@@ -2,3 +2,5 @@ export declare const GELATO_NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEee
2
2
  export declare const GELATO_FEE_COLLECTOR = "0x3AC05161b76a35c1c28dC99Aa01BEd7B24cEA3bf";
3
3
  export declare const GELATO_RELAY_URL = "https://relay.gelato.digital";
4
4
  export declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
5
+ export declare const GELATO_GAS_EXECUTION_OVERHEAD = 150000;
6
+ export declare const GELATO_TRANSFER_GAS_COST = 15000;
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ZERO_ADDRESS = exports.GELATO_RELAY_URL = exports.GELATO_FEE_COLLECTOR = exports.GELATO_NATIVE_TOKEN_ADDRESS = void 0;
3
+ exports.GELATO_TRANSFER_GAS_COST = exports.GELATO_GAS_EXECUTION_OVERHEAD = exports.ZERO_ADDRESS = exports.GELATO_RELAY_URL = exports.GELATO_FEE_COLLECTOR = exports.GELATO_NATIVE_TOKEN_ADDRESS = void 0;
4
4
  exports.GELATO_NATIVE_TOKEN_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
5
5
  exports.GELATO_FEE_COLLECTOR = '0x3AC05161b76a35c1c28dC99Aa01BEd7B24cEA3bf';
6
6
  exports.GELATO_RELAY_URL = 'https://relay.gelato.digital';
7
7
  exports.ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
8
+ // see: https://docs.gelato.network/developer-services/relay/quick-start/optional-parameters#optional-parameters
9
+ exports.GELATO_GAS_EXECUTION_OVERHEAD = 150000;
10
+ // gas cost of the separate ERC20 transfer to pay the fees to the Gelato relayer
11
+ exports.GELATO_TRANSFER_GAS_COST = 15000;
8
12
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,2BAA2B,GAAG,4CAA4C,CAAA;AAE1E,QAAA,oBAAoB,GAAG,4CAA4C,CAAA;AAEnE,QAAA,gBAAgB,GAAG,8BAA8B,CAAA;AAEjD,QAAA,YAAY,GAAG,4CAA4C,CAAA"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,2BAA2B,GAAG,4CAA4C,CAAA;AAE1E,QAAA,oBAAoB,GAAG,4CAA4C,CAAA;AAEnE,QAAA,gBAAgB,GAAG,8BAA8B,CAAA;AAEjD,QAAA,YAAY,GAAG,4CAA4C,CAAA;AAExE,gHAAgH;AACnG,QAAA,6BAA6B,GAAG,MAAO,CAAA;AAEpD,gFAAgF;AACnE,QAAA,wBAAwB,GAAG,KAAM,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { RelayResponse, TransactionStatusResponse } from '@gelatonetwork/relay-sdk';
2
2
  import Safe from '@safe-global/protocol-kit';
3
- import { RelayPack } from '../../types';
4
- import { MetaTransactionData, MetaTransactionOptions, RelayTransaction, SafeTransaction } from '@safe-global/safe-core-sdk-types';
3
+ import { RelayPack, CreateTransactionProps } from '../../types';
4
+ import { MetaTransactionOptions, RelayTransaction, SafeTransaction } from '@safe-global/safe-core-sdk-types';
5
5
  export declare class GelatoRelayPack implements RelayPack {
6
6
  #private;
7
7
  constructor(apiKey?: string);
@@ -9,8 +9,59 @@ export declare class GelatoRelayPack implements RelayPack {
9
9
  getFeeCollector(): string;
10
10
  getEstimateFee(chainId: number, gasLimit: string, gasToken?: string): Promise<string>;
11
11
  getTaskStatus(taskId: string): Promise<TransactionStatusResponse | undefined>;
12
- createRelayedTransaction(safe: Safe, transactions: MetaTransactionData[], options: MetaTransactionOptions): Promise<SafeTransaction>;
12
+ /**
13
+ * Creates a payment transaction to Gelato
14
+ *
15
+ * @private
16
+ * @async
17
+ * @function
18
+ * @param {Safe} safe - The Safe object
19
+ * @param {string} gas - The gas amount for the payment.
20
+ * @param {MetaTransactionOptions} options - Options for the meta transaction.
21
+ * @returns {Promise<Transaction>} Promise object representing the created payment transaction.
22
+ *
23
+ */
24
+ private createPaymentToGelato;
25
+ /**
26
+ * Creates a Safe transaction designed to be executed using the Gelato Relayer.
27
+ *
28
+ * @param {CreateTransactionProps} createTransactionProps - Properties required to create the transaction.
29
+ * @returns {Promise<SafeTransaction>} Returns a Promise that resolves with a SafeTransaction object.
30
+ */
31
+ createRelayedTransaction({ safe, transactions, onlyCalls, options }: CreateTransactionProps): Promise<SafeTransaction>;
32
+ /**
33
+ * Creates a Safe transaction designed to be executed using the Gelato Relayer and
34
+ * uses the handlePayment function defined in the Safe contract to pay the fees
35
+ * to the Gelato relayer.
36
+ *
37
+ * @async
38
+ * @function createTransactionWithHandlePayment
39
+ * @param {CreateTransactionProps} createTransactionProps - Properties needed to create the transaction.
40
+ * @returns {Promise<SafeTransaction>} Returns a promise that resolves to the created SafeTransaction.
41
+ * @private
42
+ */
43
+ private createTransactionWithHandlePayment;
44
+ /**
45
+ * Creates a Safe transaction designed to be executed using the Gelato Relayer and
46
+ * uses a separate ERC20 transfer to pay the fees to the Gelato relayer.
47
+ *
48
+ * @async
49
+ * @function createTransactionWithTransfer
50
+ * @param {CreateTransactionProps} createTransactionProps - Properties needed to create the transaction.
51
+ * @returns {Promise<SafeTransaction>} Returns a promise that resolves to the created SafeTransaction.
52
+ * @private
53
+ */
54
+ private createTransactionWithTransfer;
13
55
  sendSponsorTransaction(target: string, encodedTransaction: string, chainId: number): Promise<RelayResponse>;
14
56
  sendSyncTransaction(target: string, encodedTransaction: string, chainId: number, options: MetaTransactionOptions): Promise<RelayResponse>;
15
57
  relayTransaction({ target, encodedTransaction, chainId, options }: RelayTransaction): Promise<RelayResponse>;
58
+ /**
59
+ * Sends the Safe transaction to the Gelato Relayer for execution.
60
+ * If the Safe is not deployed, it creates a batch of transactions including the Safe deployment transaction.
61
+ *
62
+ * @param {SafeTransaction} safeTransaction - The Safe transaction to be executed.
63
+ * @param {Safe} safe - The Safe object related to the transaction.
64
+ * @returns {Promise<RelayResponse>} Returns a Promise that resolves with a RelayResponse object.
65
+ */
66
+ executeRelayTransaction(safeTransaction: SafeTransaction, safe: Safe, options?: MetaTransactionOptions): Promise<RelayResponse>;
16
67
  }
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.GelatoRelayPack = void 0;
16
16
  const bignumber_1 = require("@ethersproject/bignumber");
17
17
  const relay_sdk_1 = require("@gelatonetwork/relay-sdk");
18
+ const protocol_kit_1 = require("@safe-global/protocol-kit");
18
19
  const constants_1 = require("../../constants");
19
20
  class GelatoRelayPack {
20
21
  constructor(apiKey) {
@@ -31,36 +32,182 @@ class GelatoRelayPack {
31
32
  }
32
33
  async getEstimateFee(chainId, gasLimit, gasToken) {
33
34
  const feeToken = this._getFeeToken(gasToken);
34
- const estimation = await __classPrivateFieldGet(this, _GelatoRelayPack_gelatoRelay, "f").getEstimatedFee(chainId, feeToken, bignumber_1.BigNumber.from(gasLimit), true);
35
+ const estimation = await __classPrivateFieldGet(this, _GelatoRelayPack_gelatoRelay, "f").getEstimatedFee(chainId, feeToken, bignumber_1.BigNumber.from(gasLimit), false);
35
36
  return estimation.toString();
36
37
  }
37
38
  async getTaskStatus(taskId) {
38
39
  return __classPrivateFieldGet(this, _GelatoRelayPack_gelatoRelay, "f").getTaskStatus(taskId);
39
40
  }
40
- async createRelayedTransaction(safe, transactions, options) {
41
- const { gasLimit, gasToken, isSponsored } = options;
42
- const nonce = await safe.getNonce();
41
+ /**
42
+ * Creates a payment transaction to Gelato
43
+ *
44
+ * @private
45
+ * @async
46
+ * @function
47
+ * @param {Safe} safe - The Safe object
48
+ * @param {string} gas - The gas amount for the payment.
49
+ * @param {MetaTransactionOptions} options - Options for the meta transaction.
50
+ * @returns {Promise<Transaction>} Promise object representing the created payment transaction.
51
+ *
52
+ */
53
+ async createPaymentToGelato(safe, gas, options) {
54
+ const chainId = await safe.getChainId();
55
+ const gelatoAddress = this.getFeeCollector();
56
+ const gasToken = options.gasToken ?? constants_1.ZERO_ADDRESS;
57
+ const paymentToGelato = await this.getEstimateFee(chainId, gas, gasToken);
58
+ // The Gelato payment transaction
59
+ const transferToGelato = (0, protocol_kit_1.createERC20TokenTransferTransaction)(gasToken, gelatoAddress, paymentToGelato);
60
+ return transferToGelato;
61
+ }
62
+ /**
63
+ * Creates a Safe transaction designed to be executed using the Gelato Relayer.
64
+ *
65
+ * @param {CreateTransactionProps} createTransactionProps - Properties required to create the transaction.
66
+ * @returns {Promise<SafeTransaction>} Returns a Promise that resolves with a SafeTransaction object.
67
+ */
68
+ async createRelayedTransaction({ safe, transactions, onlyCalls = false, options = {} }) {
69
+ const { isSponsored = false } = options;
43
70
  if (isSponsored) {
71
+ const nonce = await safe.getNonce();
44
72
  const sponsoredTransaction = await safe.createTransaction({
45
73
  safeTransactionData: transactions,
74
+ onlyCalls,
46
75
  options: {
47
76
  nonce
48
77
  }
49
78
  });
50
79
  return sponsoredTransaction;
51
80
  }
81
+ // If the ERC20 gas token does not follow the standard 18 decimals, we cannot use handlePayment to pay Gelato fees.
82
+ const gasToken = options.gasToken ?? constants_1.ZERO_ADDRESS;
83
+ const isGasTokenCompatible = await (0, protocol_kit_1.isGasTokenCompatibleWithHandlePayment)(gasToken, safe);
84
+ if (!isGasTokenCompatible) {
85
+ // if the ERC20 gas token is not compatible (less than 18 decimals like USDC), a separate transfer is required to pay Gelato fees.
86
+ return this.createTransactionWithTransfer({ safe, transactions, onlyCalls, options });
87
+ }
88
+ // If the gas token is compatible (Native token or standard ERC20), we use handlePayment function present in the Safe contract to pay Gelato fees
89
+ return this.createTransactionWithHandlePayment({ safe, transactions, onlyCalls, options });
90
+ }
91
+ /**
92
+ * Creates a Safe transaction designed to be executed using the Gelato Relayer and
93
+ * uses the handlePayment function defined in the Safe contract to pay the fees
94
+ * to the Gelato relayer.
95
+ *
96
+ * @async
97
+ * @function createTransactionWithHandlePayment
98
+ * @param {CreateTransactionProps} createTransactionProps - Properties needed to create the transaction.
99
+ * @returns {Promise<SafeTransaction>} Returns a promise that resolves to the created SafeTransaction.
100
+ * @private
101
+ */
102
+ async createTransactionWithHandlePayment({ safe, transactions, onlyCalls = false, options = {} }) {
103
+ const { gasLimit } = options;
104
+ const nonce = await safe.getNonce();
105
+ // this transaction is only used for gas estimations
106
+ const transactionToEstimateGas = await safe.createTransaction({
107
+ safeTransactionData: transactions,
108
+ onlyCalls,
109
+ options: {
110
+ nonce
111
+ }
112
+ });
113
+ // as we set gasPrice to 1, safeTxGas is set to a non-zero value to prevent transaction failure due to out-of-gas errors. value see: https://github.com/safe-global/safe-contracts/blob/main/contracts/Safe.sol#L203
114
+ const gasPrice = '1';
115
+ const safeTxGas = await (0, protocol_kit_1.estimateSafeTxGas)(safe, transactionToEstimateGas);
116
+ const gasToken = options.gasToken ?? constants_1.ZERO_ADDRESS;
117
+ const refundReceiver = this.getFeeCollector();
52
118
  const chainId = await safe.getChainId();
53
- const estimation = await this.getEstimateFee(chainId, gasLimit, gasToken);
119
+ // if a custom gasLimit is provided, we do not need to estimate the gas cost
120
+ if (gasLimit) {
121
+ const paymentToGelato = await this.getEstimateFee(chainId, gasLimit, gasToken);
122
+ const syncTransaction = await safe.createTransaction({
123
+ safeTransactionData: transactions,
124
+ onlyCalls,
125
+ options: {
126
+ baseGas: paymentToGelato,
127
+ gasPrice,
128
+ safeTxGas,
129
+ gasToken,
130
+ refundReceiver,
131
+ nonce
132
+ }
133
+ });
134
+ return syncTransaction;
135
+ }
136
+ // If gasLimit is not provided, we need to estimate the gas cost.
137
+ const baseGas = await (0, protocol_kit_1.estimateTxBaseGas)(safe, transactionToEstimateGas);
138
+ const safeDeploymentGasCost = await (0, protocol_kit_1.estimateSafeDeploymentGas)(safe);
139
+ const totalGas = Number(baseGas) + // baseGas
140
+ Number(safeTxGas) + // safeTxGas
141
+ Number(safeDeploymentGasCost) + // Safe deploymet gas cost if it is required
142
+ constants_1.GELATO_GAS_EXECUTION_OVERHEAD; // Gelato execution overhead
143
+ const paymentToGelato = await this.getEstimateFee(chainId, String(totalGas), gasToken);
54
144
  const syncTransaction = await safe.createTransaction({
55
145
  safeTransactionData: transactions,
146
+ onlyCalls,
147
+ options: {
148
+ baseGas: paymentToGelato,
149
+ gasPrice,
150
+ safeTxGas,
151
+ gasToken,
152
+ refundReceiver,
153
+ nonce
154
+ }
155
+ });
156
+ return syncTransaction;
157
+ }
158
+ /**
159
+ * Creates a Safe transaction designed to be executed using the Gelato Relayer and
160
+ * uses a separate ERC20 transfer to pay the fees to the Gelato relayer.
161
+ *
162
+ * @async
163
+ * @function createTransactionWithTransfer
164
+ * @param {CreateTransactionProps} createTransactionProps - Properties needed to create the transaction.
165
+ * @returns {Promise<SafeTransaction>} Returns a promise that resolves to the created SafeTransaction.
166
+ * @private
167
+ */
168
+ async createTransactionWithTransfer({ safe, transactions, onlyCalls = false, options = {} }) {
169
+ const { gasLimit } = options;
170
+ const nonce = await safe.getNonce();
171
+ const gasToken = options.gasToken ?? constants_1.ZERO_ADDRESS;
172
+ // if a custom gasLimit is provided, we do not need to estimate the gas cost
173
+ if (gasLimit) {
174
+ const transferToGelato = await this.createPaymentToGelato(safe, gasLimit, options);
175
+ const syncTransaction = await safe.createTransaction({
176
+ safeTransactionData: [...transactions, transferToGelato],
177
+ onlyCalls,
178
+ options: {
179
+ nonce,
180
+ gasToken
181
+ }
182
+ });
183
+ return syncTransaction;
184
+ }
185
+ // If gasLimit is not provided, we need to estimate the gas cost.
186
+ // this transaction is only used for gas estimations
187
+ const transactionToEstimateGas = await safe.createTransaction({
188
+ safeTransactionData: transactions,
189
+ onlyCalls,
56
190
  options: {
57
- baseGas: estimation,
58
- gasPrice: '1',
59
- gasToken: gasToken !== null && gasToken !== void 0 ? gasToken : constants_1.ZERO_ADDRESS,
60
- refundReceiver: this.getFeeCollector(),
61
191
  nonce
62
192
  }
63
193
  });
194
+ const safeTxGas = await (0, protocol_kit_1.estimateSafeTxGas)(safe, transactionToEstimateGas);
195
+ const baseGas = await (0, protocol_kit_1.estimateTxBaseGas)(safe, transactionToEstimateGas);
196
+ const safeDeploymentGasCost = await (0, protocol_kit_1.estimateSafeDeploymentGas)(safe);
197
+ const totalGas = Number(baseGas) + // baseGas
198
+ Number(safeTxGas) + // safeTxGas without Gelato payment transfer
199
+ Number(safeDeploymentGasCost) + // Safe deploymet gas cost if it is required
200
+ constants_1.GELATO_TRANSFER_GAS_COST + // Gelato payment transfer
201
+ constants_1.GELATO_GAS_EXECUTION_OVERHEAD; // Gelato execution overhead
202
+ const transferToGelato = await this.createPaymentToGelato(safe, String(totalGas), options);
203
+ const syncTransaction = await safe.createTransaction({
204
+ safeTransactionData: [...transactions, transferToGelato],
205
+ onlyCalls,
206
+ options: {
207
+ nonce,
208
+ gasToken
209
+ }
210
+ });
64
211
  return syncTransaction;
65
212
  }
66
213
  async sendSponsorTransaction(target, encodedTransaction, chainId) {
@@ -91,12 +238,51 @@ class GelatoRelayPack {
91
238
  const response = await __classPrivateFieldGet(this, _GelatoRelayPack_gelatoRelay, "f").callWithSyncFee(request, relayRequestOptions);
92
239
  return response;
93
240
  }
94
- async relayTransaction({ target, encodedTransaction, chainId, options }) {
241
+ async relayTransaction({ target, encodedTransaction, chainId, options = {} }) {
95
242
  const response = options.isSponsored
96
243
  ? this.sendSponsorTransaction(target, encodedTransaction, chainId)
97
244
  : this.sendSyncTransaction(target, encodedTransaction, chainId, options);
98
245
  return response;
99
246
  }
247
+ /**
248
+ * Sends the Safe transaction to the Gelato Relayer for execution.
249
+ * If the Safe is not deployed, it creates a batch of transactions including the Safe deployment transaction.
250
+ *
251
+ * @param {SafeTransaction} safeTransaction - The Safe transaction to be executed.
252
+ * @param {Safe} safe - The Safe object related to the transaction.
253
+ * @returns {Promise<RelayResponse>} Returns a Promise that resolves with a RelayResponse object.
254
+ */
255
+ async executeRelayTransaction(safeTransaction, safe, options) {
256
+ const isSafeDeployed = await safe.isSafeDeployed();
257
+ const chainId = await safe.getChainId();
258
+ const safeAddress = await safe.getAddress();
259
+ const safeTransactionEncodedData = await safe.getEncodedTransaction(safeTransaction);
260
+ const gasToken = options?.gasToken || safeTransaction.data.gasToken;
261
+ if (isSafeDeployed) {
262
+ const relayTransaction = {
263
+ target: safeAddress,
264
+ encodedTransaction: safeTransactionEncodedData,
265
+ chainId,
266
+ options: {
267
+ ...options,
268
+ gasToken
269
+ }
270
+ };
271
+ return this.relayTransaction(relayTransaction);
272
+ }
273
+ // if the Safe is not deployed we create a batch with the Safe deployment transaction and the provided Safe transaction
274
+ const safeDeploymentBatch = await safe.wrapSafeTransactionIntoDeploymentBatch(safeTransaction);
275
+ const relayTransaction = {
276
+ target: safeDeploymentBatch.to,
277
+ encodedTransaction: safeDeploymentBatch.data,
278
+ chainId,
279
+ options: {
280
+ ...options,
281
+ gasToken
282
+ }
283
+ };
284
+ return this.relayTransaction(relayTransaction);
285
+ }
100
286
  }
101
287
  exports.GelatoRelayPack = GelatoRelayPack;
102
288
  _GelatoRelayPack_gelatoRelay = new WeakMap(), _GelatoRelayPack_apiKey = new WeakMap();
@@ -1 +1 @@
1
- {"version":3,"file":"GelatoRelayPack.js","sourceRoot":"","sources":["../../../../src/packs/gelato/GelatoRelayPack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GelatoRelayPack.js","sourceRoot":"","sources":["../../../../src/packs/gelato/GelatoRelayPack.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wDAAoD;AACpD,wDAOiC;AACjC,4DAMkC;AAClC,gEAMyC;AASzC,MAAa,eAAe;IAI1B,YAAY,MAAe;QAH3B,+CAAgC;QAChC,0CAAgB;QAGd,uBAAA,IAAI,gCAAgB,IAAI,uBAAkB,EAAE,MAAA,CAAA;QAC5C,uBAAA,IAAI,2BAAW,MAAM,MAAA,CAAA;IACvB,CAAC;IAEO,YAAY,CAAC,QAAiB;QACpC,OAAO,CAAC,QAAQ,IAAI,QAAQ,KAAK,wBAAY,CAAC,CAAC,CAAC,uCAA2B,CAAC,CAAC,CAAC,QAAQ,CAAA;IACxF,CAAC;IAED,eAAe;QACb,OAAO,gCAAoB,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,QAAgB,EAAE,QAAiB;QACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC5C,MAAM,UAAU,GAAG,MAAM,uBAAA,IAAI,oCAAa,CAAC,eAAe,CACxD,OAAO,EACP,QAAQ,EACR,qBAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EACxB,KAAK,CACN,CAAA;QACD,OAAO,UAAU,CAAC,QAAQ,EAAE,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,MAAc;QAChC,OAAO,uBAAA,IAAI,oCAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;IAChD,CAAC;IAED;;;;;;;;;;;OAWG;IACK,KAAK,CAAC,qBAAqB,CACjC,IAAU,EACV,GAAW,EACX,OAA+B;QAE/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QACvC,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;QAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,wBAAY,CAAA;QAEjD,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAA;QAEzE,iCAAiC;QACjC,MAAM,gBAAgB,GAAG,IAAA,kDAAmC,EAC1D,QAAQ,EACR,aAAa,EACb,eAAe,CAChB,CAAA;QAED,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,wBAAwB,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,SAAS,GAAG,KAAK,EACjB,OAAO,GAAG,EAAE,EACW;QACvB,MAAM,EAAE,WAAW,GAAG,KAAK,EAAE,GAAG,OAAO,CAAA;QAEvC,IAAI,WAAW,EAAE;YACf,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;YAEnC,MAAM,oBAAoB,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;gBACxD,mBAAmB,EAAE,YAAY;gBACjC,SAAS;gBACT,OAAO,EAAE;oBACP,KAAK;iBACN;aACF,CAAC,CAAA;YAEF,OAAO,oBAAoB,CAAA;SAC5B;QAED,mHAAmH;QAEnH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,wBAAY,CAAA;QACjD,MAAM,oBAAoB,GAAG,MAAM,IAAA,oDAAqC,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QAExF,IAAI,CAAC,oBAAoB,EAAE;YACzB,kIAAkI;YAElI,OAAO,IAAI,CAAC,6BAA6B,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;SACtF;QAED,iJAAiJ;QACjJ,OAAO,IAAI,CAAC,kCAAkC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAA;IAC5F,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,kCAAkC,CAAC,EAC/C,IAAI,EACJ,YAAY,EACZ,SAAS,GAAG,KAAK,EACjB,OAAO,GAAG,EAAE,EACW;QACvB,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;QAC5B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;QAEnC,oDAAoD;QACpD,MAAM,wBAAwB,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;YAC5D,mBAAmB,EAAE,YAAY;YACjC,SAAS;YACT,OAAO,EAAE;gBACP,KAAK;aACN;SACF,CAAC,CAAA;QAEF,oNAAoN;QACpN,MAAM,QAAQ,GAAG,GAAG,CAAA;QACpB,MAAM,SAAS,GAAG,MAAM,IAAA,gCAAiB,EAAC,IAAI,EAAE,wBAAwB,CAAC,CAAA;QACzE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,wBAAY,CAAA;QACjD,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;QAC7C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QAEvC,4EAA4E;QAC5E,IAAI,QAAQ,EAAE;YACZ,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAE9E,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;gBACnD,mBAAmB,EAAE,YAAY;gBACjC,SAAS;gBACT,OAAO,EAAE;oBACP,OAAO,EAAE,eAAe;oBACxB,QAAQ;oBACR,SAAS;oBACT,QAAQ;oBACR,cAAc;oBACd,KAAK;iBACN;aACF,CAAC,CAAA;YAEF,OAAO,eAAe,CAAA;SACvB;QAED,iEAAiE;QAEjE,MAAM,OAAO,GAAG,MAAM,IAAA,gCAAiB,EAAC,IAAI,EAAE,wBAAwB,CAAC,CAAA;QACvE,MAAM,qBAAqB,GAAG,MAAM,IAAA,wCAAyB,EAAC,IAAI,CAAC,CAAA;QAEnE,MAAM,QAAQ,GACZ,MAAM,CAAC,OAAO,CAAC,GAAG,UAAU;YAC5B,MAAM,CAAC,SAAS,CAAC,GAAG,YAAY;YAChC,MAAM,CAAC,qBAAqB,CAAC,GAAG,4CAA4C;YAC5E,yCAA6B,CAAA,CAAC,4BAA4B;QAE5D,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAA;QAEtF,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;YACnD,mBAAmB,EAAE,YAAY;YACjC,SAAS;YACT,OAAO,EAAE;gBACP,OAAO,EAAE,eAAe;gBACxB,QAAQ;gBACR,SAAS;gBACT,QAAQ;gBACR,cAAc;gBACd,KAAK;aACN;SACF,CAAC,CAAA;QAEF,OAAO,eAAe,CAAA;IACxB,CAAC;IAED;;;;;;;;;OASG;IACK,KAAK,CAAC,6BAA6B,CAAC,EAC1C,IAAI,EACJ,YAAY,EACZ,SAAS,GAAG,KAAK,EACjB,OAAO,GAAG,EAAE,EACW;QACvB,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;QAC5B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA;QACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,wBAAY,CAAA;QAEjD,4EAA4E;QAC5E,IAAI,QAAQ,EAAE;YACZ,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;YAElF,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;gBACnD,mBAAmB,EAAE,CAAC,GAAG,YAAY,EAAE,gBAAgB,CAAC;gBACxD,SAAS;gBACT,OAAO,EAAE;oBACP,KAAK;oBACL,QAAQ;iBACT;aACF,CAAC,CAAA;YAEF,OAAO,eAAe,CAAA;SACvB;QAED,iEAAiE;QAEjE,oDAAoD;QACpD,MAAM,wBAAwB,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;YAC5D,mBAAmB,EAAE,YAAY;YACjC,SAAS;YACT,OAAO,EAAE;gBACP,KAAK;aACN;SACF,CAAC,CAAA;QAEF,MAAM,SAAS,GAAG,MAAM,IAAA,gCAAiB,EAAC,IAAI,EAAE,wBAAwB,CAAC,CAAA;QACzE,MAAM,OAAO,GAAG,MAAM,IAAA,gCAAiB,EAAC,IAAI,EAAE,wBAAwB,CAAC,CAAA;QACvE,MAAM,qBAAqB,GAAG,MAAM,IAAA,wCAAyB,EAAC,IAAI,CAAC,CAAA;QAEnE,MAAM,QAAQ,GACZ,MAAM,CAAC,OAAO,CAAC,GAAG,UAAU;YAC5B,MAAM,CAAC,SAAS,CAAC,GAAG,4CAA4C;YAChE,MAAM,CAAC,qBAAqB,CAAC,GAAG,4CAA4C;YAC5E,oCAAwB,GAAG,0BAA0B;YACrD,yCAA6B,CAAA,CAAC,4BAA4B;QAE5D,MAAM,gBAAgB,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAA;QAE1F,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC;YACnD,mBAAmB,EAAE,CAAC,GAAG,YAAY,EAAE,gBAAgB,CAAC;YACxD,SAAS;YACT,OAAO,EAAE;gBACP,KAAK;gBACL,QAAQ;aACT;SACF,CAAC,CAAA;QAEF,OAAO,eAAe,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,sBAAsB,CAC1B,MAAc,EACd,kBAA0B,EAC1B,OAAe;QAEf,IAAI,CAAC,uBAAA,IAAI,+BAAQ,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;SACvC;QACD,MAAM,OAAO,GAAyB;YACpC,OAAO;YACP,MAAM;YACN,IAAI,EAAE,kBAAkB;SACzB,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,oCAAa,CAAC,aAAa,CAAC,OAAO,EAAE,uBAAA,IAAI,+BAAQ,CAAC,CAAA;QAC7E,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,MAAc,EACd,kBAA0B,EAC1B,OAAe,EACf,OAA+B;QAE/B,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC5C,MAAM,OAAO,GAA2B;YACtC,OAAO;YACP,MAAM;YACN,IAAI,EAAE,kBAAkB;YACxB,QAAQ;YACR,cAAc,EAAE,KAAK;SACtB,CAAA;QACD,MAAM,mBAAmB,GAAwB;YAC/C,QAAQ;SACT,CAAA;QACD,MAAM,QAAQ,GAAG,MAAM,uBAAA,IAAI,oCAAa,CAAC,eAAe,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAA;QACtF,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EACrB,MAAM,EACN,kBAAkB,EAClB,OAAO,EACP,OAAO,GAAG,EAAE,EACK;QACjB,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW;YAClC,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,kBAAkB,EAAE,OAAO,CAAC;YAClE,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QAC1E,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,uBAAuB,CAC3B,eAAgC,EAChC,IAAU,EACV,OAAgC;QAEhC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAA;QAClD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QACvC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QAC3C,MAAM,0BAA0B,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAA;QAEpF,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAA;QAEnE,IAAI,cAAc,EAAE;YAClB,MAAM,gBAAgB,GAAqB;gBACzC,MAAM,EAAE,WAAW;gBACnB,kBAAkB,EAAE,0BAA0B;gBAC9C,OAAO;gBACP,OAAO,EAAE;oBACP,GAAG,OAAO;oBACV,QAAQ;iBACT;aACF,CAAA;YAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;SAC/C;QAED,uHAAuH;QACvH,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,sCAAsC,CAAC,eAAe,CAAC,CAAA;QAE9F,MAAM,gBAAgB,GAAqB;YACzC,MAAM,EAAE,mBAAmB,CAAC,EAAE;YAC9B,kBAAkB,EAAE,mBAAmB,CAAC,IAAI;YAC5C,OAAO;YACP,OAAO,EAAE;gBACP,GAAG,OAAO;gBACV,QAAQ;aACT;SACF,CAAA;QAED,OAAO,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;IAChD,CAAC;CACF;AA7WD,0CA6WC"}