diff --git a/cold-wallet-app/lib/debug/debug_payloads.dart b/cold-wallet-app/lib/debug/debug_payloads.dart index 055e039aa..077dfbedd 100644 --- a/cold-wallet-app/lib/debug/debug_payloads.dart +++ b/cold-wallet-app/lib/debug/debug_payloads.dart @@ -25,7 +25,6 @@ class DebugPayloads { /// combination can be eyeballed without a hot wallet. static final Map all = { 'Send': transfer, - 'Force send': forceTransfer, 'Reversible': reversibleTransfer, 'Reversible 8h': reversibleTransferWithDelay, 'Msig approve': multisigApproveTransfer, @@ -38,19 +37,6 @@ class DebugPayloads { return withExtensions(_send(BigInt.from(1500000000000))); // 1.5 tokens } - /// A root-level transfer of another account's funds. The screen must show - /// the Source row and say `Signed by`, never `From`: the funds do not leave - /// the signer. - static Uint8List forceTransfer() { - return withExtensions( - const balances_pallet.Txs().forceTransfer( - source: multi_address.MultiAddress.values.id(_debugSourceAccount), - dest: _address(AppConstants.debugTestAddress), - value: BigInt.from(2500000000000), // 2.5 tokens - ), - ); - } - /// A reversible transfer on the account's default window. /// Headline: REVERSIBLE SEND. static Uint8List reversibleTransfer() { @@ -110,9 +96,6 @@ class DebugPayloads { /// checkphrase without needing a real on-chain multisig. static final Uint8List _debugMultisigAccount = Uint8List.fromList(List.filled(32, 0xA7)); - /// Synthetic force_transfer source, distinct from every other address shown. - static final Uint8List _debugSourceAccount = Uint8List.fromList(List.filled(32, 0xF0)); - static multi_address.MultiAddress _address(String ss58) => multi_address.MultiAddress.values.id(ss58ToAccountId(s: ss58)); diff --git a/cold-wallet-app/test/call_display_test.dart b/cold-wallet-app/test/call_display_test.dart index c963e5e3e..661d9b192 100644 --- a/cold-wallet-app/test/call_display_test.dart +++ b/cold-wallet-app/test/call_display_test.dart @@ -82,10 +82,12 @@ void main() { }); testWidgets('signer row reads Signed by when the funds leave an explicit source', (tester) async { + // A multisig proposal moves the multisig account's funds, not the signer's. + final inner = const balances_pallet.Txs().transferAllowDeath(dest: account(bobId), value: oneToken); await pumpSignScreen( tester, DebugPayloads.withExtensions( - const balances_pallet.Txs().forceTransfer(source: account(aliceId), dest: account(bobId), value: oneToken), + const multisig_pallet.Txs().propose(multisigAddress: aliceId, call: inner.encode(), expiry: 5000), ), ); expect(find.text('SIGNED BY'), findsOneWidget); diff --git a/mobile-app/lib/services/transaction_submission_service.dart b/mobile-app/lib/services/transaction_submission_service.dart index 293fed067..5a42d9f6d 100644 --- a/mobile-app/lib/services/transaction_submission_service.dart +++ b/mobile-app/lib/services/transaction_submission_service.dart @@ -289,6 +289,7 @@ class TransactionSubmissionService { required MultisigAccount msig, required Account signer, required MultisigProposal proposal, + List? callBytes, BigInt? fee, }) async { final pending = PendingMultisigExecutionEvent.fromProposal( @@ -302,7 +303,7 @@ class TransactionSubmissionService { TelemetryService().sendEvent('multisig_execute'); - await _submitExecute(msig: msig, signer: signer, proposalId: proposal.id, pending: pending); + await _submitExecute(msig: msig, signer: signer, proposalId: proposal.id, callBytes: callBytes, pending: pending); } Future _submitExecute({ @@ -310,10 +311,16 @@ class TransactionSubmissionService { required Account signer, required int proposalId, required PendingMultisigExecutionEvent pending, + List? callBytes, }) async { try { final service = _ref.read(multisigServiceProvider); - final hashBytes = await service.submitExecuteExtrinsic(msig: msig, signer: signer, proposalId: proposalId); + final hashBytes = await service.submitExecuteExtrinsic( + msig: msig, + signer: signer, + proposalId: proposalId, + callBytes: callBytes, + ); final extrinsicHash = '0x${hex.encode(hashBytes)}'; quantusPrint('[Execute] submitted: $extrinsicHash'); diff --git a/mobile-app/lib/v2/screens/multisig/multisig_action_confirm_sheet.dart b/mobile-app/lib/v2/screens/multisig/multisig_action_confirm_sheet.dart index 8c1243ff1..2100952bc 100644 --- a/mobile-app/lib/v2/screens/multisig/multisig_action_confirm_sheet.dart +++ b/mobile-app/lib/v2/screens/multisig/multisig_action_confirm_sheet.dart @@ -38,6 +38,10 @@ typedef MultisigConfirmCallBuilder = RuntimeCall Function(Account signer, List> Function(WidgetRef ref); +/// The stored inner call, which a resubmitting action cannot be built without. +List requireCallBytes(List? callBytes, String action) => + callBytes ?? (throw StateError('$action requires the proposal call bytes')); + /// Submits a hardware-signed extrinsic for the action. typedef MultisigConfirmExternalSubmitter = Future Function( diff --git a/mobile-app/lib/v2/screens/multisig/multisig_approve_confirm_sheet.dart b/mobile-app/lib/v2/screens/multisig/multisig_approve_confirm_sheet.dart index 4e064fd52..53c0b5a49 100644 --- a/mobile-app/lib/v2/screens/multisig/multisig_approve_confirm_sheet.dart +++ b/mobile-app/lib/v2/screens/multisig/multisig_approve_confirm_sheet.dart @@ -45,7 +45,7 @@ void showMultisigApproveConfirmSheet( buildCall: (resolvedSigner, callBytes) => MultisigService().buildApproveCall( msig: msig, proposalId: proposal.id, - call: callBytes ?? (throw StateError('Approve requires the proposal call bytes')), + call: requireCallBytes(callBytes, 'Approve'), ), submit: (ref, resolvedSigner, fee, callBytes) => ref .read(transactionSubmissionServiceProvider) diff --git a/mobile-app/lib/v2/screens/multisig/multisig_execute_confirm_sheet.dart b/mobile-app/lib/v2/screens/multisig/multisig_execute_confirm_sheet.dart index f1fcd8cc5..f949b2eac 100644 --- a/mobile-app/lib/v2/screens/multisig/multisig_execute_confirm_sheet.dart +++ b/mobile-app/lib/v2/screens/multisig/multisig_execute_confirm_sheet.dart @@ -33,12 +33,17 @@ void showMultisigExecuteConfirmSheet( // could not execute anyway. loadCallBytes: (ref) => ref.read(multisigServiceProvider).fetchProposalCallBytes(msig: msig, proposalId: proposal.id), - estimateFee: (ref, signer, callBytes) => - ref.read(multisigServiceProvider).estimateExecuteFee(msig: msig, signer: signer, proposalId: proposal.id), - buildCall: (signer, callBytes) => MultisigService().buildExecuteCall(msig: msig, proposalId: proposal.id), + estimateFee: (ref, signer, callBytes) => ref + .read(multisigServiceProvider) + .estimateExecuteFee(msig: msig, signer: signer, proposalId: proposal.id, callBytes: callBytes), + buildCall: (signer, callBytes) => MultisigService().buildExecuteCall( + msig: msig, + proposalId: proposal.id, + call: requireCallBytes(callBytes, 'Execute'), + ), submit: (ref, signer, fee, callBytes) => ref .read(transactionSubmissionServiceProvider) - .executeProposal(msig: msig, signer: signer, proposal: proposal, fee: fee), + .executeProposal(msig: msig, signer: signer, proposal: proposal, fee: fee, callBytes: callBytes), submitExternal: (ref, {required signer, required unsignedData, required signature, required publicKey, fee}) => ref .read(transactionSubmissionServiceProvider) diff --git a/mobile-app/test/unit/multisig_require_call_bytes_test.dart b/mobile-app/test/unit/multisig_require_call_bytes_test.dart new file mode 100644 index 000000000..6d8834bda --- /dev/null +++ b/mobile-app/test/unit/multisig_require_call_bytes_test.dart @@ -0,0 +1,25 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:resonance_network_wallet/v2/screens/multisig/multisig_action_confirm_sheet.dart'; + +void main() { + group('requireCallBytes', () { + test('returns the stored call bytes unchanged', () { + const bytes = [0x02, 0x00, 0x07]; + expect(requireCallBytes(bytes, 'Execute'), same(bytes)); + }); + + test('throws rather than build an action without the call it must resubmit', () { + // Approve and execute are both bound to the proposal's exact bytes, so a + // missing load must fail loudly instead of submitting a call the chain rejects. + expect(() => requireCallBytes(null, 'Execute'), throwsA(isA())); + expect(() => requireCallBytes(null, 'Approve'), throwsA(isA())); + }); + + test('names the action in the error', () { + expect( + () => requireCallBytes(null, 'Execute'), + throwsA(isA().having((e) => e.message, 'message', contains('Execute'))), + ); + }); + }); +} diff --git a/quantus_sdk/lib/generated/planck/pallets/balances.dart b/quantus_sdk/lib/generated/planck/pallets/balances.dart index be3312a96..6a99ebaf1 100644 --- a/quantus_sdk/lib/generated/planck/pallets/balances.dart +++ b/quantus_sdk/lib/generated/planck/pallets/balances.dart @@ -9,7 +9,6 @@ import '../types/frame_support/traits/tokens/misc/id_amount_1.dart' as _i7; import '../types/frame_support/traits/tokens/misc/id_amount_2.dart' as _i8; import '../types/pallet_balances/pallet/call.dart' as _i13; import '../types/pallet_balances/types/account_data.dart' as _i4; -import '../types/pallet_balances/types/adjustment_direction.dart' as _i14; import '../types/pallet_balances/types/balance_lock.dart' as _i5; import '../types/pallet_balances/types/reserve_data.dart' as _i6; import '../types/quantus_runtime/runtime_call.dart' as _i11; @@ -351,16 +350,6 @@ class Txs { return _i11.Balances(_i13.TransferAllowDeath(dest: dest, value: value)); } - /// Exactly as `transfer_allow_death`, except the origin must be root and the source account - /// may be specified. - _i11.Balances forceTransfer({ - required _i12.MultiAddress source, - required _i12.MultiAddress dest, - required BigInt value, - }) { - return _i11.Balances(_i13.ForceTransfer(source: source, dest: dest, value: value)); - } - /// Same as the [`transfer_allow_death`] call, but with a check that the transfer will not /// kill the origin account. /// @@ -390,41 +379,6 @@ class Txs { return _i11.Balances(_i13.TransferAll(dest: dest, keepAlive: keepAlive)); } - /// Unreserve some balance from a user by force. - /// - /// Can only be called by ROOT. - _i11.Balances forceUnreserve({required _i12.MultiAddress who, required BigInt amount}) { - return _i11.Balances(_i13.ForceUnreserve(who: who, amount: amount)); - } - - /// Upgrade a specified account. - /// - /// - `origin`: Must be `Signed`. - /// - `who`: The account to be upgraded. - /// - /// This will waive the transaction fee if at least all but 10% of the accounts needed to - /// be upgraded. (We let some not have to be upgraded just in order to allow for the - /// possibility of churn). - _i11.Balances upgradeAccounts({required List<_i3.AccountId32> who}) { - return _i11.Balances(_i13.UpgradeAccounts(who: who)); - } - - /// Set the regular balance of a given account. - /// - /// The dispatch origin for this call is `root`. - _i11.Balances forceSetBalance({required _i12.MultiAddress who, required BigInt newFree}) { - return _i11.Balances(_i13.ForceSetBalance(who: who, newFree: newFree)); - } - - /// Adjust the total issuance in a saturating way. - /// - /// Can only be called by root and always needs a positive `delta`. - /// - /// # Example - _i11.Balances forceAdjustTotalIssuance({required _i14.AdjustmentDirection direction, required BigInt delta}) { - return _i11.Balances(_i13.ForceAdjustTotalIssuance(direction: direction, delta: delta)); - } - /// Burn the specified liquid free balance from the origin account. /// /// If the origin's account ends up below the existential deposit as a result diff --git a/quantus_sdk/lib/generated/planck/pallets/multisig.dart b/quantus_sdk/lib/generated/planck/pallets/multisig.dart index 1cbd394ac..f3aa8a59f 100644 --- a/quantus_sdk/lib/generated/planck/pallets/multisig.dart +++ b/quantus_sdk/lib/generated/planck/pallets/multisig.dart @@ -104,7 +104,8 @@ class Txs { /// The multisig address is deterministically derived from: /// hash(pallet_id || sorted_signers || threshold || nonce) /// - /// Signers are automatically sorted before hashing, so order doesn't matter. + /// Signers are sorted before hashing, so order doesn't matter. + /// Duplicate accounts are rejected. /// /// Economic costs: /// - MultisigFee: burned immediately (spam prevention) @@ -199,20 +200,35 @@ class Txs { /// Can be called by any signer of the multisig once the proposal has reached /// the approval threshold (status = Approved). The proposal must not be expired. /// + /// The executor resubmits the proposal's inner call; execution proceeds only + /// if it is byte-equal to the payload stored at `proposal_id` — the same + /// binding `approve` enforces. This serves two purposes: + /// - **Clearsigning:** the executor's (hardware) wallet displays and signs the actual call + /// being dispatched, not an opaque proposal id. + /// - **Self-describing weight:** the executing extrinsic carries the inner call, so its + /// declared weight carries the inner call's own declared weight (refunded to actuals + /// post-dispatch) instead of reserving a flat `MaxInnerCallWeight`, and runtime + /// transaction extensions can inspect the inner call and price its side effects + /// (account-reap cleanup, transfer-proof recording) exactly as they do for directly + /// submitted calls. Nothing about the dispatch is invisible to pre-dispatch admission or + /// fees. (Only the bookkeeping term is reserved at `MaxCallSize`, since the stored bytes' + /// length is unknown pre-dispatch; the unused remainder is refunded.) + /// /// On execution: - /// - The call is decoded and dispatched as the multisig account + /// - The call is dispatched as the multisig account /// - Proposal is removed from storage /// - Deposit is returned to the proposer /// /// Parameters: /// - `multisig_address`: The multisig account /// - `proposal_id`: ID (nonce) of the proposal to execute - /// - /// Note: The weight charged includes both multisig bookkeeping and MaxInnerCallWeight. - /// Actual weight is refunded based on the inner call's post-dispatch info. - /// The inner call's weight is validated against MaxInnerCallWeight at propose time. - _i8.Multisig execute({required _i2.AccountId32 multisigAddress, required int proposalId}) { - return _i8.Multisig(_i9.Execute(multisigAddress: multisigAddress, proposalId: proposalId)); + /// - `call`: The proposal's inner call, byte-equal to the stored payload + _i8.Multisig execute({ + required _i2.AccountId32 multisigAddress, + required int proposalId, + required _i8.RuntimeCall call, + }) { + return _i8.Multisig(_i9.Execute(multisigAddress: multisigAddress, proposalId: proposalId, call: call)); } } diff --git a/quantus_sdk/lib/generated/planck/pallets/recovery.dart b/quantus_sdk/lib/generated/planck/pallets/recovery.dart deleted file mode 100644 index 4e0e81349..000000000 --- a/quantus_sdk/lib/generated/planck/pallets/recovery.dart +++ /dev/null @@ -1,338 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i5; -import 'dart:typed_data' as _i6; - -import 'package:polkadart/polkadart.dart' as _i1; - -import '../types/pallet_recovery/active_recovery.dart' as _i4; -import '../types/pallet_recovery/pallet/call.dart' as _i9; -import '../types/pallet_recovery/recovery_config.dart' as _i3; -import '../types/quantus_runtime/runtime_call.dart' as _i7; -import '../types/sp_core/crypto/account_id32.dart' as _i2; -import '../types/sp_runtime/multiaddress/multi_address.dart' as _i8; - -class Queries { - const Queries(this.__api); - - final _i1.StateApi __api; - - final _i1.StorageMap<_i2.AccountId32, _i3.RecoveryConfig> _recoverable = - const _i1.StorageMap<_i2.AccountId32, _i3.RecoveryConfig>( - prefix: 'Recovery', - storage: 'Recoverable', - valueCodec: _i3.RecoveryConfig.codec, - hasher: _i1.StorageHasher.twoxx64Concat(_i2.AccountId32Codec()), - ); - - final _i1.StorageDoubleMap<_i2.AccountId32, _i2.AccountId32, _i4.ActiveRecovery> _activeRecoveries = - const _i1.StorageDoubleMap<_i2.AccountId32, _i2.AccountId32, _i4.ActiveRecovery>( - prefix: 'Recovery', - storage: 'ActiveRecoveries', - valueCodec: _i4.ActiveRecovery.codec, - hasher1: _i1.StorageHasher.twoxx64Concat(_i2.AccountId32Codec()), - hasher2: _i1.StorageHasher.twoxx64Concat(_i2.AccountId32Codec()), - ); - - final _i1.StorageMap<_i2.AccountId32, _i2.AccountId32> _proxy = - const _i1.StorageMap<_i2.AccountId32, _i2.AccountId32>( - prefix: 'Recovery', - storage: 'Proxy', - valueCodec: _i2.AccountId32Codec(), - hasher: _i1.StorageHasher.blake2b128Concat(_i2.AccountId32Codec()), - ); - - /// The set of recoverable accounts and their recovery configuration. - _i5.Future<_i3.RecoveryConfig?> recoverable(_i2.AccountId32 key1, {_i1.BlockHash? at}) async { - final hashedKey = _recoverable.hashedKeyFor(key1); - final bytes = await __api.getStorage(hashedKey, at: at); - if (bytes != null) { - return _recoverable.decodeValue(bytes); - } - return null; /* Nullable */ - } - - /// Active recovery attempts. - /// - /// First account is the account to be recovered, and the second account - /// is the user trying to recover the account. - _i5.Future<_i4.ActiveRecovery?> activeRecoveries( - _i2.AccountId32 key1, - _i2.AccountId32 key2, { - _i1.BlockHash? at, - }) async { - final hashedKey = _activeRecoveries.hashedKeyFor(key1, key2); - final bytes = await __api.getStorage(hashedKey, at: at); - if (bytes != null) { - return _activeRecoveries.decodeValue(bytes); - } - return null; /* Nullable */ - } - - /// The list of allowed proxy accounts. - /// - /// Map from the user who can access it to the recovered account. - _i5.Future<_i2.AccountId32?> proxy(_i2.AccountId32 key1, {_i1.BlockHash? at}) async { - final hashedKey = _proxy.hashedKeyFor(key1); - final bytes = await __api.getStorage(hashedKey, at: at); - if (bytes != null) { - return _proxy.decodeValue(bytes); - } - return null; /* Nullable */ - } - - /// The set of recoverable accounts and their recovery configuration. - _i5.Future> multiRecoverable(List<_i2.AccountId32> keys, {_i1.BlockHash? at}) async { - final hashedKeys = keys.map((key) => _recoverable.hashedKeyFor(key)).toList(); - final bytes = await __api.queryStorageAt(hashedKeys, at: at); - if (bytes.isNotEmpty) { - return bytes.first.changes.map((v) => _recoverable.decodeValue(v.key)).toList(); - } - return []; /* Nullable */ - } - - /// The list of allowed proxy accounts. - /// - /// Map from the user who can access it to the recovered account. - _i5.Future> multiProxy(List<_i2.AccountId32> keys, {_i1.BlockHash? at}) async { - final hashedKeys = keys.map((key) => _proxy.hashedKeyFor(key)).toList(); - final bytes = await __api.queryStorageAt(hashedKeys, at: at); - if (bytes.isNotEmpty) { - return bytes.first.changes.map((v) => _proxy.decodeValue(v.key)).toList(); - } - return []; /* Nullable */ - } - - /// Returns the storage key for `recoverable`. - _i6.Uint8List recoverableKey(_i2.AccountId32 key1) { - final hashedKey = _recoverable.hashedKeyFor(key1); - return hashedKey; - } - - /// Returns the storage key for `activeRecoveries`. - _i6.Uint8List activeRecoveriesKey(_i2.AccountId32 key1, _i2.AccountId32 key2) { - final hashedKey = _activeRecoveries.hashedKeyFor(key1, key2); - return hashedKey; - } - - /// Returns the storage key for `proxy`. - _i6.Uint8List proxyKey(_i2.AccountId32 key1) { - final hashedKey = _proxy.hashedKeyFor(key1); - return hashedKey; - } - - /// Returns the storage map key prefix for `recoverable`. - _i6.Uint8List recoverableMapPrefix() { - final hashedKey = _recoverable.mapPrefix(); - return hashedKey; - } - - /// Returns the storage map key prefix for `activeRecoveries`. - _i6.Uint8List activeRecoveriesMapPrefix(_i2.AccountId32 key1) { - final hashedKey = _activeRecoveries.mapPrefix(key1); - return hashedKey; - } - - /// Returns the storage map key prefix for `proxy`. - _i6.Uint8List proxyMapPrefix() { - final hashedKey = _proxy.mapPrefix(); - return hashedKey; - } -} - -class Txs { - const Txs(); - - /// Send a call through a recovered account. - /// - /// The dispatch origin for this call must be _Signed_ and registered to - /// be able to make calls on behalf of the recovered account. - /// - /// Parameters: - /// - `account`: The recovered account you want to make a call on-behalf-of. - /// - `call`: The call you want to make with the recovered account. - _i7.Recovery asRecovered({required _i8.MultiAddress account, required _i7.RuntimeCall call}) { - return _i7.Recovery(_i9.AsRecovered(account: account, call: call)); - } - - /// Allow ROOT to bypass the recovery process and set a rescuer account - /// for a lost account directly. - /// - /// The dispatch origin for this call must be _ROOT_. - /// - /// Parameters: - /// - `lost`: The "lost account" to be recovered. - /// - `rescuer`: The "rescuer account" which can call as the lost account. - _i7.Recovery setRecovered({required _i8.MultiAddress lost, required _i8.MultiAddress rescuer}) { - return _i7.Recovery(_i9.SetRecovered(lost: lost, rescuer: rescuer)); - } - - /// Create a recovery configuration for your account. This makes your account recoverable. - /// - /// Payment: `ConfigDepositBase` + `FriendDepositFactor` * #_of_friends balance - /// will be reserved for storing the recovery configuration. This deposit is returned - /// in full when the user calls `remove_recovery`. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// Parameters: - /// - `friends`: A list of friends you trust to vouch for recovery attempts. Should be - /// ordered and contain no duplicate values. - /// - `threshold`: The number of friends that must vouch for a recovery attempt before the - /// account can be recovered. Should be less than or equal to the length of the list of - /// friends. - /// - `delay_period`: The number of blocks after a recovery attempt is initialized that - /// needs to pass before the account can be recovered. - _i7.Recovery createRecovery({ - required List<_i2.AccountId32> friends, - required int threshold, - required int delayPeriod, - }) { - return _i7.Recovery(_i9.CreateRecovery(friends: friends, threshold: threshold, delayPeriod: delayPeriod)); - } - - /// Initiate the process for recovering a recoverable account. - /// - /// Payment: `RecoveryDeposit` balance will be reserved for initiating the - /// recovery process. This deposit will always be repatriated to the account - /// trying to be recovered. See `close_recovery`. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// Parameters: - /// - `account`: The lost account that you want to recover. This account needs to be - /// recoverable (i.e. have a recovery configuration). - _i7.Recovery initiateRecovery({required _i8.MultiAddress account}) { - return _i7.Recovery(_i9.InitiateRecovery(account: account)); - } - - /// Allow a "friend" of a recoverable account to vouch for an active recovery - /// process for that account. - /// - /// The dispatch origin for this call must be _Signed_ and must be a "friend" - /// for the recoverable account. - /// - /// Parameters: - /// - `lost`: The lost account that you want to recover. - /// - `rescuer`: The account trying to rescue the lost account that you want to vouch for. - /// - /// The combination of these two parameters must point to an active recovery - /// process. - _i7.Recovery vouchRecovery({required _i8.MultiAddress lost, required _i8.MultiAddress rescuer}) { - return _i7.Recovery(_i9.VouchRecovery(lost: lost, rescuer: rescuer)); - } - - /// Allow a successful rescuer to claim their recovered account. - /// - /// The dispatch origin for this call must be _Signed_ and must be a "rescuer" - /// who has successfully completed the account recovery process: collected - /// `threshold` or more vouches, waited `delay_period` blocks since initiation. - /// - /// Parameters: - /// - `account`: The lost account that you want to claim has been successfully recovered by - /// you. - _i7.Recovery claimRecovery({required _i8.MultiAddress account}) { - return _i7.Recovery(_i9.ClaimRecovery(account: account)); - } - - /// As the controller of a recoverable account, close an active recovery - /// process for your account. - /// - /// Payment: By calling this function, the recoverable account will receive - /// the recovery deposit `RecoveryDeposit` placed by the rescuer. - /// - /// The dispatch origin for this call must be _Signed_ and must be a - /// recoverable account with an active recovery process for it. - /// - /// Parameters: - /// - `rescuer`: The account trying to rescue this recoverable account. - _i7.Recovery closeRecovery({required _i8.MultiAddress rescuer}) { - return _i7.Recovery(_i9.CloseRecovery(rescuer: rescuer)); - } - - /// Remove the recovery process for your account. Recovered accounts are still accessible. - /// - /// NOTE: The user must make sure to call `close_recovery` on all active - /// recovery attempts before calling this function else it will fail. - /// - /// Payment: By calling this function the recoverable account will unreserve - /// their recovery configuration deposit. - /// (`ConfigDepositBase` + `FriendDepositFactor` * #_of_friends) - /// - /// The dispatch origin for this call must be _Signed_ and must be a - /// recoverable account (i.e. has a recovery configuration). - _i7.Recovery removeRecovery() { - return _i7.Recovery(_i9.RemoveRecovery()); - } - - /// Cancel the ability to use `as_recovered` for `account`. - /// - /// The dispatch origin for this call must be _Signed_ and registered to - /// be able to make calls on behalf of the recovered account. - /// - /// Parameters: - /// - `account`: The recovered account you are able to call on-behalf-of. - _i7.Recovery cancelRecovered({required _i8.MultiAddress account}) { - return _i7.Recovery(_i9.CancelRecovered(account: account)); - } - - /// Poke deposits for recovery configurations and / or active recoveries. - /// - /// This can be used by accounts to possibly lower their locked amount. - /// - /// The dispatch origin for this call must be _Signed_. - /// - /// Parameters: - /// - `maybe_account`: Optional recoverable account for which you have an active recovery - /// and want to adjust the deposit for the active recovery. - /// - /// This function checks both recovery configuration deposit and active recovery deposits - /// of the caller: - /// - If the caller has created a recovery configuration, checks and adjusts its deposit - /// - If the caller has initiated any active recoveries, and provides the account in - /// `maybe_account`, checks and adjusts those deposits - /// - /// If any deposit is updated, the difference will be reserved/unreserved from the caller's - /// account. - /// - /// The transaction is made free if any deposit is updated and paid otherwise. - /// - /// Emits `DepositPoked` if any deposit is updated. - /// Multiple events may be emitted in case both types of deposits are updated. - _i7.Recovery pokeDeposit({_i8.MultiAddress? maybeAccount}) { - return _i7.Recovery(_i9.PokeDeposit(maybeAccount: maybeAccount)); - } -} - -class Constants { - Constants(); - - /// The base amount of currency needed to reserve for creating a recovery configuration. - /// - /// This is held for an additional storage item whose value size is - /// `2 + sizeof(BlockNumber, Balance)` bytes. - final BigInt configDepositBase = BigInt.from(10000000000000); - - /// The amount of currency needed per additional user when creating a recovery - /// configuration. - /// - /// This is held for adding `sizeof(AccountId)` bytes more into a pre-existing storage - /// value. - final BigInt friendDepositFactor = BigInt.from(1000000000000); - - /// The maximum amount of friends allowed in a recovery configuration. - /// - /// NOTE: The threshold programmed in this Pallet uses u16, so it does - /// not really make sense to have a limit here greater than u16::MAX. - /// But also, that is a lot more than you should probably set this value - /// to anyway... - final int maxFriends = 9; - - /// The base amount of currency needed to reserve for starting a recovery. - /// - /// This is primarily held for deterring malicious recovery attempts, and should - /// have a value large enough that a bad actor would choose not to place this - /// deposit. It also acts to fund additional storage item whose value size is - /// `sizeof(BlockNumber, Balance + T * AccountId)` bytes. Where T is a configurable - /// threshold. - final BigInt recoveryDeposit = BigInt.from(10000000000000); -} diff --git a/quantus_sdk/lib/generated/planck/pallets/reversible_transfers.dart b/quantus_sdk/lib/generated/planck/pallets/reversible_transfers.dart index 8fec6a8e3..f1f4fd9e1 100644 --- a/quantus_sdk/lib/generated/planck/pallets/reversible_transfers.dart +++ b/quantus_sdk/lib/generated/planck/pallets/reversible_transfers.dart @@ -3,12 +3,12 @@ import 'dart:async' as _i7; import 'dart:typed_data' as _i8; import 'package:polkadart/polkadart.dart' as _i1; -import 'package:polkadart/scale_codec.dart' as _i6; +import 'package:polkadart/scale_codec.dart' as _i4; import '../types/pallet_reversible_transfers/high_security_account_data.dart' as _i3; import '../types/pallet_reversible_transfers/pallet/call.dart' as _i11; -import '../types/pallet_reversible_transfers/pending_transfer.dart' as _i5; -import '../types/primitive_types/h256.dart' as _i4; +import '../types/pallet_reversible_transfers/pending_transfer.dart' as _i6; +import '../types/primitive_types/h256.dart' as _i5; import '../types/qp_scheduler/block_number_or_timestamp.dart' as _i10; import '../types/quantus_runtime/runtime_call.dart' as _i9; import '../types/sp_arithmetic/per_things/permill.dart' as _i13; @@ -28,34 +28,34 @@ class Queries { hasher: _i1.StorageHasher.blake2b128Concat(_i2.AccountId32Codec()), ); - final _i1.StorageMap<_i4.H256, _i5.PendingTransfer> _pendingTransfers = - const _i1.StorageMap<_i4.H256, _i5.PendingTransfer>( + final _i1.StorageMap<_i2.AccountId32, List> _highSecurityTxQuota = + const _i1.StorageMap<_i2.AccountId32, List>( prefix: 'ReversibleTransfers', - storage: 'PendingTransfers', - valueCodec: _i5.PendingTransfer.codec, - hasher: _i1.StorageHasher.blake2b128Concat(_i4.H256Codec()), + storage: 'HighSecurityTxQuota', + valueCodec: _i4.U32SequenceCodec.codec, + hasher: _i1.StorageHasher.blake2b128Concat(_i2.AccountId32Codec()), ); - final _i1.StorageMap<_i2.AccountId32, List<_i4.H256>> _pendingTransfersBySender = - const _i1.StorageMap<_i2.AccountId32, List<_i4.H256>>( + final _i1.StorageMap<_i5.H256, _i6.PendingTransfer> _pendingTransfers = + const _i1.StorageMap<_i5.H256, _i6.PendingTransfer>( prefix: 'ReversibleTransfers', - storage: 'PendingTransfersBySender', - valueCodec: _i6.SequenceCodec<_i4.H256>(_i4.H256Codec()), - hasher: _i1.StorageHasher.blake2b128Concat(_i2.AccountId32Codec()), + storage: 'PendingTransfers', + valueCodec: _i6.PendingTransfer.codec, + hasher: _i1.StorageHasher.blake2b128Concat(_i5.H256Codec()), ); - final _i1.StorageMap<_i2.AccountId32, List<_i2.AccountId32>> _guardianIndex = - const _i1.StorageMap<_i2.AccountId32, List<_i2.AccountId32>>( + final _i1.StorageMap<_i2.AccountId32, List<_i5.H256>> _pendingTransfersBySender = + const _i1.StorageMap<_i2.AccountId32, List<_i5.H256>>( prefix: 'ReversibleTransfers', - storage: 'GuardianIndex', - valueCodec: _i6.SequenceCodec<_i2.AccountId32>(_i2.AccountId32Codec()), + storage: 'PendingTransfersBySender', + valueCodec: _i4.SequenceCodec<_i5.H256>(_i5.H256Codec()), hasher: _i1.StorageHasher.blake2b128Concat(_i2.AccountId32Codec()), ); final _i1.StorageValue _nextTransactionId = const _i1.StorageValue( prefix: 'ReversibleTransfers', storage: 'NextTransactionId', - valueCodec: _i6.U64Codec.codec, + valueCodec: _i4.U64Codec.codec, ); /// Maps accounts to their chosen reversibility delay period (in milliseconds). @@ -69,9 +69,23 @@ class Queries { return null; /* Nullable */ } + /// Rolling window of included signed extrinsics for each high-security account. + /// + /// Oldest block number is at index 0. Recording a tx is O(1): compare + /// `now - oldest` to [`Config::HighSecurityTxWindowBlocks`], maybe evict + /// that one head, then push. Normal accounts are not stored here. + _i7.Future> highSecurityTxQuota(_i2.AccountId32 key1, {_i1.BlockHash? at}) async { + final hashedKey = _highSecurityTxQuota.hashedKeyFor(key1); + final bytes = await __api.getStorage(hashedKey, at: at); + if (bytes != null) { + return _highSecurityTxQuota.decodeValue(bytes); + } + return List.filled(0, 0, growable: true); /* Default */ + } + /// Stores the details of pending transactions scheduled for delayed execution. /// Keyed by the unique transaction ID. - _i7.Future<_i5.PendingTransfer?> pendingTransfers(_i4.H256 key1, {_i1.BlockHash? at}) async { + _i7.Future<_i6.PendingTransfer?> pendingTransfers(_i5.H256 key1, {_i1.BlockHash? at}) async { final hashedKey = _pendingTransfers.hashedKeyFor(key1); final bytes = await __api.getStorage(hashedKey, at: at); if (bytes != null) { @@ -81,7 +95,7 @@ class Queries { } /// Maps sender accounts to their list of pending transaction IDs. - _i7.Future> pendingTransfersBySender(_i2.AccountId32 key1, {_i1.BlockHash? at}) async { + _i7.Future> pendingTransfersBySender(_i2.AccountId32 key1, {_i1.BlockHash? at}) async { final hashedKey = _pendingTransfersBySender.hashedKeyFor(key1); final bytes = await __api.getStorage(hashedKey, at: at); if (bytes != null) { @@ -90,18 +104,6 @@ class Queries { return []; /* Default */ } - /// Maps guardian accounts to the list of accounts they protect. - /// This allows the UI to efficiently query all accounts for which a given account is a - /// guardian. - _i7.Future> guardianIndex(_i2.AccountId32 key1, {_i1.BlockHash? at}) async { - final hashedKey = _guardianIndex.hashedKeyFor(key1); - final bytes = await __api.getStorage(hashedKey, at: at); - if (bytes != null) { - return _guardianIndex.decodeValue(bytes); - } - return []; /* Default */ - } - /// Monotonically increasing counter used to generate unique transaction IDs. /// Each scheduled transfer increments this value to ensure no two transfers /// produce the same `tx_id`, even if they have identical parameters. @@ -128,9 +130,23 @@ class Queries { return []; /* Nullable */ } + /// Rolling window of included signed extrinsics for each high-security account. + /// + /// Oldest block number is at index 0. Recording a tx is O(1): compare + /// `now - oldest` to [`Config::HighSecurityTxWindowBlocks`], maybe evict + /// that one head, then push. Normal accounts are not stored here. + _i7.Future>> multiHighSecurityTxQuota(List<_i2.AccountId32> keys, {_i1.BlockHash? at}) async { + final hashedKeys = keys.map((key) => _highSecurityTxQuota.hashedKeyFor(key)).toList(); + final bytes = await __api.queryStorageAt(hashedKeys, at: at); + if (bytes.isNotEmpty) { + return bytes.first.changes.map((v) => _highSecurityTxQuota.decodeValue(v.key)).toList(); + } + return (keys.map((key) => List.filled(0, 0, growable: true)).toList() as List>); /* Default */ + } + /// Stores the details of pending transactions scheduled for delayed execution. /// Keyed by the unique transaction ID. - _i7.Future> multiPendingTransfers(List<_i4.H256> keys, {_i1.BlockHash? at}) async { + _i7.Future> multiPendingTransfers(List<_i5.H256> keys, {_i1.BlockHash? at}) async { final hashedKeys = keys.map((key) => _pendingTransfers.hashedKeyFor(key)).toList(); final bytes = await __api.queryStorageAt(hashedKeys, at: at); if (bytes.isNotEmpty) { @@ -140,7 +156,7 @@ class Queries { } /// Maps sender accounts to their list of pending transaction IDs. - _i7.Future>> multiPendingTransfersBySender( + _i7.Future>> multiPendingTransfersBySender( List<_i2.AccountId32> keys, { _i1.BlockHash? at, }) async { @@ -149,19 +165,7 @@ class Queries { if (bytes.isNotEmpty) { return bytes.first.changes.map((v) => _pendingTransfersBySender.decodeValue(v.key)).toList(); } - return (keys.map((key) => []).toList() as List>); /* Default */ - } - - /// Maps guardian accounts to the list of accounts they protect. - /// This allows the UI to efficiently query all accounts for which a given account is a - /// guardian. - _i7.Future>> multiGuardianIndex(List<_i2.AccountId32> keys, {_i1.BlockHash? at}) async { - final hashedKeys = keys.map((key) => _guardianIndex.hashedKeyFor(key)).toList(); - final bytes = await __api.queryStorageAt(hashedKeys, at: at); - if (bytes.isNotEmpty) { - return bytes.first.changes.map((v) => _guardianIndex.decodeValue(v.key)).toList(); - } - return (keys.map((key) => []).toList() as List>); /* Default */ + return (keys.map((key) => []).toList() as List>); /* Default */ } /// Returns the storage key for `highSecurityAccounts`. @@ -170,8 +174,14 @@ class Queries { return hashedKey; } + /// Returns the storage key for `highSecurityTxQuota`. + _i8.Uint8List highSecurityTxQuotaKey(_i2.AccountId32 key1) { + final hashedKey = _highSecurityTxQuota.hashedKeyFor(key1); + return hashedKey; + } + /// Returns the storage key for `pendingTransfers`. - _i8.Uint8List pendingTransfersKey(_i4.H256 key1) { + _i8.Uint8List pendingTransfersKey(_i5.H256 key1) { final hashedKey = _pendingTransfers.hashedKeyFor(key1); return hashedKey; } @@ -182,12 +192,6 @@ class Queries { return hashedKey; } - /// Returns the storage key for `guardianIndex`. - _i8.Uint8List guardianIndexKey(_i2.AccountId32 key1) { - final hashedKey = _guardianIndex.hashedKeyFor(key1); - return hashedKey; - } - /// Returns the storage key for `nextTransactionId`. _i8.Uint8List nextTransactionIdKey() { final hashedKey = _nextTransactionId.hashedKey(); @@ -200,6 +204,12 @@ class Queries { return hashedKey; } + /// Returns the storage map key prefix for `highSecurityTxQuota`. + _i8.Uint8List highSecurityTxQuotaMapPrefix() { + final hashedKey = _highSecurityTxQuota.mapPrefix(); + return hashedKey; + } + /// Returns the storage map key prefix for `pendingTransfers`. _i8.Uint8List pendingTransfersMapPrefix() { final hashedKey = _pendingTransfers.mapPrefix(); @@ -211,12 +221,6 @@ class Queries { final hashedKey = _pendingTransfersBySender.mapPrefix(); return hashedKey; } - - /// Returns the storage map key prefix for `guardianIndex`. - _i8.Uint8List guardianIndexMapPrefix() { - final hashedKey = _guardianIndex.mapPrefix(); - return hashedKey; - } } class Txs { @@ -257,6 +261,21 @@ class Txs { /// - `delay`: The reversibility time for any transfer made by the high-security account. /// - `guardian`: The guardian account that can cancel pending transfers and recover funds /// from this high-security account. + /// + /// # Choose the guardian carefully + /// + /// The guardian holds instant, total seizure power: `recover_funds` + /// sweeps every hold plus the entire free balance to the guardian, + /// with no delay, no second approver, and no way to change the + /// relationship afterwards. A single-key guardian is therefore a + /// single point of failure for the whole scheme. **Use a multisig + /// address as the guardian**: `pallet_multisig` dispatches calls as + /// its derived address, so a multisig can cancel and recover exactly + /// like a plain account. + /// + /// Guardianship is discoverable offchain (e.g. Subsquid) via the + /// `HighSecuritySet` event; there is deliberately no on-chain + /// guardian index to fill up or grief. _i9.ReversibleTransfers setHighSecurity({ required _i10.BlockNumberOrTimestamp delay, required _i2.AccountId32 guardian, @@ -267,7 +286,7 @@ class Txs { /// Cancel a pending reversible transaction scheduled by the caller. /// /// - `tx_id`: The unique identifier of the transaction to cancel. - _i9.ReversibleTransfers cancel({required _i4.H256 txId}) { + _i9.ReversibleTransfers cancel({required _i5.H256 txId}) { return _i9.ReversibleTransfers(_i11.Cancel(txId: txId)); } @@ -282,12 +301,21 @@ class Txs { /// /// - `tx_id`: The unique identifier of the pending transfer to execute. /// + /// Execution uses `transfer_allow_death` so a sender who spent their leftover + /// free balance during the delay still completes. A failed inner transfer (e.g. + /// dest overflow, or `amount < ED` to a new account) does not fail this + /// extrinsic: the hold is already released and the pending transfer is already + /// removed. Propagating that error would roll back those writes (FRAME + /// dispatchables are transactional) while Scheduler terminally drops the named + /// task, freezing the funds with no retry. The inner result is still recorded on + /// [`Event::TransactionExecuted`]. + /// /// # Errors /// /// - [`InvalidSchedulerOrigin`](Error::InvalidSchedulerOrigin): Called by an account other /// than this pallet's account. /// - [`PendingTxNotFound`](Error::PendingTxNotFound): No pending transfer with this ID. - _i9.ReversibleTransfers executeTransfer({required _i4.H256 txId}) { + _i9.ReversibleTransfers executeTransfer({required _i5.H256 txId}) { return _i9.ReversibleTransfers(_i11.ExecuteTransfer(txId: txId)); } @@ -353,12 +381,17 @@ class Txs { class Constants { Constants(); - /// Maximum number of accounts a single guardian can protect. Used for BoundedVec. - final int maxGuardianAccounts = 32; - /// Maximum pending reversible transactions allowed per account. final int maxPendingPerAccount = 16; + /// Maximum signed extrinsics a high-security account may include in one + /// rolling window. Update of the quota ring is O(1). + final int maxHighSecurityTxsPerWindow = 16; + + /// Length of the high-security extrinsic quota window, in blocks. + /// At the runtime's 12s target this is one day (`DAYS`). + final int highSecurityTxWindowBlocks = 7200; + /// The default delay period for reversible transactions if none is specified. /// /// NOTE: default delay is always in blocks. diff --git a/quantus_sdk/lib/generated/planck/pallets/system.dart b/quantus_sdk/lib/generated/planck/pallets/system.dart index fa8b228bb..1186a228c 100644 --- a/quantus_sdk/lib/generated/planck/pallets/system.dart +++ b/quantus_sdk/lib/generated/planck/pallets/system.dart @@ -703,16 +703,16 @@ class Constants { /// Block & extrinsics weights: base values and limits. final _i19.BlockWeights blockWeights = _i19.BlockWeights( - baseBlock: _i13.Weight(refTime: BigInt.from(431614000), proofSize: BigInt.zero), + baseBlock: _i13.Weight(refTime: BigInt.from(710231000), proofSize: BigInt.zero), maxBlock: _i13.Weight( refTime: BigInt.from(6000000000000), proofSize: BigInt.parse('18446744073709551615', radix: 10), ), perClass: _i20.PerDispatchClass( normal: _i21.WeightsPerClass( - baseExtrinsic: _i13.Weight(refTime: BigInt.from(108157000), proofSize: BigInt.zero), + baseExtrinsic: _i13.Weight(refTime: BigInt.from(767297000), proofSize: BigInt.zero), maxExtrinsic: _i13.Weight( - refTime: BigInt.from(3899460229000), + refTime: BigInt.from(3898522472000), proofSize: BigInt.parse('11990383647911208550', radix: 10), ), maxTotal: _i13.Weight( @@ -722,9 +722,9 @@ class Constants { reserved: _i13.Weight(refTime: BigInt.zero, proofSize: BigInt.zero), ), operational: _i21.WeightsPerClass( - baseExtrinsic: _i13.Weight(refTime: BigInt.from(108157000), proofSize: BigInt.zero), + baseExtrinsic: _i13.Weight(refTime: BigInt.from(767297000), proofSize: BigInt.zero), maxExtrinsic: _i13.Weight( - refTime: BigInt.from(5399460229000), + refTime: BigInt.from(5398522472000), proofSize: BigInt.parse('16602069666338596454', radix: 10), ), maxTotal: _i13.Weight( @@ -737,7 +737,7 @@ class Constants { ), ), mandatory: _i21.WeightsPerClass( - baseExtrinsic: _i13.Weight(refTime: BigInt.from(108157000), proofSize: BigInt.zero), + baseExtrinsic: _i13.Weight(refTime: BigInt.from(767297000), proofSize: BigInt.zero), maxExtrinsic: null, maxTotal: null, reserved: null, @@ -764,7 +764,7 @@ class Constants { specName: 'quantus-runtime', implName: 'quantus-runtime', authoringVersion: 1, - specVersion: 144, + specVersion: 147, implVersion: 1, apis: [ _i9.Tuple2, int>([223, 106, 203, 104, 153, 7, 96, 155], 5), @@ -780,7 +780,7 @@ class Constants { _i9.Tuple2, int>([243, 255, 20, 213, 171, 82, 112, 89], 3), _i9.Tuple2, int>([251, 197, 119, 185, 215, 71, 239, 214], 1), ], - transactionVersion: 3, + transactionVersion: 6, systemVersion: 1, ); diff --git a/quantus_sdk/lib/generated/planck/pallets/treasury_pallet.dart b/quantus_sdk/lib/generated/planck/pallets/treasury_pallet.dart index 806804106..4ee20232b 100644 --- a/quantus_sdk/lib/generated/planck/pallets/treasury_pallet.dart +++ b/quantus_sdk/lib/generated/planck/pallets/treasury_pallet.dart @@ -1,12 +1,11 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; -import 'dart:typed_data' as _i5; +import 'dart:async' as _i3; +import 'dart:typed_data' as _i4; import 'package:polkadart/polkadart.dart' as _i1; -import '../types/pallet_treasury/pallet/call.dart' as _i7; -import '../types/quantus_runtime/runtime_call.dart' as _i6; -import '../types/sp_arithmetic/per_things/permill.dart' as _i3; +import '../types/pallet_treasury/pallet/call.dart' as _i6; +import '../types/quantus_runtime/runtime_call.dart' as _i5; import '../types/sp_core/crypto/account_id32.dart' as _i2; class Queries { @@ -20,14 +19,8 @@ class Queries { valueCodec: _i2.AccountId32Codec(), ); - final _i1.StorageValue<_i3.Permill> _treasuryPortion = const _i1.StorageValue<_i3.Permill>( - prefix: 'TreasuryPallet', - storage: 'TreasuryPortion', - valueCodec: _i3.PermillCodec(), - ); - - /// The treasury account that receives mining rewards. - _i4.Future<_i2.AccountId32?> treasuryAccount({_i1.BlockHash? at}) async { + /// The treasury account that holds treasury funds. + _i3.Future<_i2.AccountId32?> treasuryAccount({_i1.BlockHash? at}) async { final hashedKey = _treasuryAccount.hashedKey(); final bytes = await __api.getStorage(hashedKey, at: at); if (bytes != null) { @@ -36,28 +29,11 @@ class Queries { return null; /* Nullable */ } - /// The portion of mining rewards that goes to treasury (Permill, 0–100%). - /// Uses OptionQuery so genesis is required. Permill allows fine granularity (e.g. 33.3%). - _i4.Future<_i3.Permill?> treasuryPortion({_i1.BlockHash? at}) async { - final hashedKey = _treasuryPortion.hashedKey(); - final bytes = await __api.getStorage(hashedKey, at: at); - if (bytes != null) { - return _treasuryPortion.decodeValue(bytes); - } - return null; /* Nullable */ - } - /// Returns the storage key for `treasuryAccount`. - _i5.Uint8List treasuryAccountKey() { + _i4.Uint8List treasuryAccountKey() { final hashedKey = _treasuryAccount.hashedKey(); return hashedKey; } - - /// Returns the storage key for `treasuryPortion`. - _i5.Uint8List treasuryPortionKey() { - final hashedKey = _treasuryPortion.hashedKey(); - return hashedKey; - } } class Txs { @@ -65,16 +41,11 @@ class Txs { /// Set the treasury account. Root only. Zero address is rejected (funds would be locked). /// - /// **Important**: This only changes where *future* mining rewards are sent. Any balance + /// **Important**: This only changes where *future* treasury credits are sent. Any balance /// that has already accumulated in the current treasury account is NOT automatically /// migrated to the new account. If you need to move existing funds, perform a separate /// balance transfer (e.g., via governance proposal) after updating the account. - _i6.TreasuryPallet setTreasuryAccount({required _i2.AccountId32 account}) { - return _i6.TreasuryPallet(_i7.SetTreasuryAccount(account: account)); - } - - /// Set the treasury portion (Permill, 0–100%). Root only. - _i6.TreasuryPallet setTreasuryPortion({required _i3.Permill portion}) { - return _i6.TreasuryPallet(_i7.SetTreasuryPortion(portion: portion)); + _i5.TreasuryPallet setTreasuryAccount({required _i2.AccountId32 account}) { + return _i5.TreasuryPallet(_i6.SetTreasuryAccount(account: account)); } } diff --git a/quantus_sdk/lib/generated/planck/pallets/utility.dart b/quantus_sdk/lib/generated/planck/pallets/utility.dart index 522516306..2ca5321f9 100644 --- a/quantus_sdk/lib/generated/planck/pallets/utility.dart +++ b/quantus_sdk/lib/generated/planck/pallets/utility.dart @@ -1,51 +1,10 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import '../types/pallet_utility/pallet/call.dart' as _i2; -import '../types/quantus_runtime/origin_caller.dart' as _i3; import '../types/quantus_runtime/runtime_call.dart' as _i1; -import '../types/sp_weights/weight_v2/weight.dart' as _i4; class Txs { const Txs(); - /// Send a batch of dispatch calls. - /// - /// May be called from any origin except `None`. - /// - /// - `calls`: The calls to be dispatched from the same origin. The number of call must not - /// exceed the constant: `batched_calls_limit` (available in constant metadata). - /// - /// If origin is root then the calls are dispatched without checking origin filter. (This - /// includes bypassing `frame_system::Config::BaseCallFilter`). - /// - /// ## Complexity - /// - O(C) where C is the number of calls to be batched. - /// - /// This will return `Ok` in all circumstances. To determine the success of the batch, an - /// event is deposited. If a call failed and the batch was interrupted, then the - /// `BatchInterrupted` event is deposited, along with the number of successful calls made - /// and the error of the failed call. If all were successful, then the `BatchCompleted` - /// event is deposited. - _i1.Utility batch({required List<_i1.RuntimeCall> calls}) { - return _i1.Utility(_i2.Batch(calls: calls)); - } - - /// Send a call through an indexed pseudonym of the sender. - /// - /// Filter from origin are passed along. The call will be dispatched with an origin which - /// use the same filter as the origin of this call. - /// - /// NOTE: If you need to ensure that any account-based filtering is not honored (i.e. - /// because you expect `proxy` to have been used prior in the call stack and you do not want - /// the call restrictions to apply to any sub-accounts), then use `as_multi_threshold_1` - /// in the Multisig pallet instead. - /// - /// NOTE: Prior to version *12, this was called `as_limited_sub`. - /// - /// The dispatch origin for this call must be _Signed_. - _i1.Utility asDerivative({required int index, required _i1.RuntimeCall call}) { - return _i1.Utility(_i2.AsDerivative(index: index, call: call)); - } - /// Send a batch of dispatch calls and atomically execute them. /// The whole transaction will rollback and fail if any of the calls failed. /// @@ -59,82 +18,12 @@ class Txs { /// /// ## Complexity /// - O(C) where C is the number of calls to be batched. + /// + /// Call index 2 is preserved from the upstream utility pallet so existing + /// `batch_all` encodings keep decoding after the other combinators were removed. _i1.Utility batchAll({required List<_i1.RuntimeCall> calls}) { return _i1.Utility(_i2.BatchAll(calls: calls)); } - - /// Dispatches a function call with a provided origin. - /// - /// The dispatch origin for this call must be _Root_. - /// - /// ## Complexity - /// - O(1). - _i1.Utility dispatchAs({required _i3.OriginCaller asOrigin, required _i1.RuntimeCall call}) { - return _i1.Utility(_i2.DispatchAs(asOrigin: asOrigin, call: call)); - } - - /// Send a batch of dispatch calls. - /// Unlike `batch`, it allows errors and won't interrupt. - /// - /// May be called from any origin except `None`. - /// - /// - `calls`: The calls to be dispatched from the same origin. The number of call must not - /// exceed the constant: `batched_calls_limit` (available in constant metadata). - /// - /// If origin is root then the calls are dispatch without checking origin filter. (This - /// includes bypassing `frame_system::Config::BaseCallFilter`). - /// - /// ## Complexity - /// - O(C) where C is the number of calls to be batched. - _i1.Utility forceBatch({required List<_i1.RuntimeCall> calls}) { - return _i1.Utility(_i2.ForceBatch(calls: calls)); - } - - /// Dispatch a function call with a specified weight. - /// - /// This function does not check the weight of the call, and instead allows the - /// Root origin to specify the weight of the call. - /// - /// The dispatch origin for this call must be _Root_. - _i1.Utility withWeight({required _i1.RuntimeCall call, required _i4.Weight weight}) { - return _i1.Utility(_i2.WithWeight(call: call, weight: weight)); - } - - /// Dispatch a fallback call in the event the main call fails to execute. - /// May be called from any origin except `None`. - /// - /// This function first attempts to dispatch the `main` call. - /// If the `main` call fails, the `fallback` is attemted. - /// if the fallback is successfully dispatched, the weights of both calls - /// are accumulated and an event containing the main call error is deposited. - /// - /// In the event of a fallback failure the whole call fails - /// with the weights returned. - /// - /// - `main`: The main call to be dispatched. This is the primary action to execute. - /// - `fallback`: The fallback call to be dispatched in case the `main` call fails. - /// - /// ## Dispatch Logic - /// - If the origin is `root`, both the main and fallback calls are executed without - /// applying any origin filters. - /// - If the origin is not `root`, the origin filter is applied to both the `main` and - /// `fallback` calls. - /// - /// ## Use Case - /// - Some use cases might involve submitting a `batch` type call in either main, fallback - /// or both. - _i1.Utility ifElse({required _i1.RuntimeCall main, required _i1.RuntimeCall fallback}) { - return _i1.Utility(_i2.IfElse(main: main, fallback: fallback)); - } - - /// Dispatches a function call with a provided origin. - /// - /// Almost the same as [`Pallet::dispatch_as`] but forwards any error of the inner call. - /// - /// The dispatch origin for this call must be _Root_. - _i1.Utility dispatchAsFallible({required _i3.OriginCaller asOrigin, required _i1.RuntimeCall call}) { - return _i1.Utility(_i2.DispatchAsFallible(asOrigin: asOrigin, call: call)); - } } class Constants { diff --git a/quantus_sdk/lib/generated/planck/pallets/vesting.dart b/quantus_sdk/lib/generated/planck/pallets/vesting.dart index 1442a9651..4a07dbfd0 100644 --- a/quantus_sdk/lib/generated/planck/pallets/vesting.dart +++ b/quantus_sdk/lib/generated/planck/pallets/vesting.dart @@ -84,7 +84,9 @@ class Txs { /// Pay the largest valid claim on `schedule_id` to its beneficiary. Payouts are /// rounded down to [`Config::PayoutQuantum`], must meet [`Config::MinimumPayout`], /// and reserve at least one minimum-sized final claim unless the schedule is fully - /// vested. + /// vested. Non-final payouts are further rounded down to + /// [`NON_FINAL_PAYOUT_QUANTA`] leaf quanta; the leftover stays on the schedule + /// until a later claim or the exact final payout. /// /// Permissionless: any signed account may call this for any schedule; the payout /// always goes to the stored beneficiary. This is the only claim path for @@ -107,19 +109,21 @@ class Txs { ); } - /// End a schedule early: the still-unpaid vested part (rounded down to a - /// [`Config::PayoutQuantum`] multiple) goes to the beneficiary, everything else - /// this schedule still holds — the unvested remainder plus any sub-quantum - /// vested dust — returns to the treasury, and the schedule is removed. The - /// treasury is signature-controlled and needs no wormhole leaf, so dust is safe - /// there but would be stranded on a keyless beneficiary. A non-zero beneficiary - /// payout below [`Config::MinimumPayout`] is rejected without ending the schedule. + /// End a schedule early: the still-unpaid vested part (rounded to the nearest + /// [`Config::PayoutQuantum`]) goes to the beneficiary if it meets + /// [`Config::MinimumPayout`]; otherwise that sliver is refunded with the + /// unvested remainder. The treasury is signature-controlled and needs no + /// wormhole leaf, so the refund is not quantized and never blocks ending. _i6.Vesting endSchedule({required BigInt scheduleId}) { return _i6.Vesting(_i7.EndSchedule(scheduleId: scheduleId)); } - /// Settle any payout a permissionless claim could currently force, then change the - /// beneficiary. This makes retargeting independent of claim transaction ordering. + /// Change the schedule's beneficiary without paying anything out. A retarget + /// replaces the wallet of the *same* grantee (lost-key remedy): the old address + /// may be lost or stolen, so settling it would burn funds or pay the thief. + /// Everything vested but unclaimed stays on the schedule and goes to the new + /// wallet at its next claim. (A permissionless claim landing before the + /// retarget still pays the old address, so rotate promptly.) _i6.Vesting retargetSchedule({required BigInt scheduleId, required _i8.AccountId32 newBeneficiary}) { return _i6.Vesting(_i7.RetargetSchedule(scheduleId: scheduleId, newBeneficiary: newBeneficiary)); } diff --git a/quantus_sdk/lib/generated/planck/pallets/zk_tree.dart b/quantus_sdk/lib/generated/planck/pallets/zk_tree.dart index 518803dd1..cfcaea659 100644 --- a/quantus_sdk/lib/generated/planck/pallets/zk_tree.dart +++ b/quantus_sdk/lib/generated/planck/pallets/zk_tree.dart @@ -46,6 +46,12 @@ class Queries { valueCodec: _i3.U8ArrayCodec(32), ); + final _i1.StorageValue _unprocessedLeaves = const _i1.StorageValue( + prefix: 'ZkTree', + storage: 'UnprocessedLeaves', + valueCodec: _i3.U64Codec.codec, + ); + /// Leaf data stored by index. _i5.Future<_i2.ZkLeaf?> leaves(BigInt key1, {_i1.BlockHash? at}) async { final hashedKey = _leaves.hashedKeyFor(key1); @@ -89,6 +95,10 @@ class Queries { } /// Current root hash of the tree. + /// + /// Covers exactly the first `LeafCount - UnprocessedLeaves` leaves: root + /// recomputation is batched once per block in `on_finalize`, so during block + /// execution this is the root as of the end of the previous block. _i5.Future> root({_i1.BlockHash? at}) async { final hashedKey = _root.hashedKey(); final bytes = await __api.getStorage(hashedKey, at: at); @@ -98,6 +108,17 @@ class Queries { return List.filled(32, 0, growable: false); /* Default */ } + /// Number of trailing leaves appended this block but not yet folded into + /// `Nodes`/`Root`. Always drained back to 0 by `on_finalize`. + _i5.Future unprocessedLeaves({_i1.BlockHash? at}) async { + final hashedKey = _unprocessedLeaves.hashedKey(); + final bytes = await __api.getStorage(hashedKey, at: at); + if (bytes != null) { + return _unprocessedLeaves.decodeValue(bytes); + } + return BigInt.zero; /* Default */ + } + /// Leaf data stored by index. _i5.Future> multiLeaves(List keys, {_i1.BlockHash? at}) async { final hashedKeys = keys.map((key) => _leaves.hashedKeyFor(key)).toList(); @@ -150,6 +171,12 @@ class Queries { return hashedKey; } + /// Returns the storage key for `unprocessedLeaves`. + _i6.Uint8List unprocessedLeavesKey() { + final hashedKey = _unprocessedLeaves.hashedKey(); + return hashedKey; + } + /// Returns the storage map key prefix for `leaves`. _i6.Uint8List leavesMapPrefix() { final hashedKey = _leaves.mapPrefix(); diff --git a/quantus_sdk/lib/generated/planck/planck.dart b/quantus_sdk/lib/generated/planck/planck.dart index 36a79df35..40de0c958 100644 --- a/quantus_sdk/lib/generated/planck/planck.dart +++ b/quantus_sdk/lib/generated/planck/planck.dart @@ -1,14 +1,13 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i20; +import 'dart:async' as _i19; import 'package:polkadart/polkadart.dart' as _i1; import 'pallets/balances.dart' as _i4; import 'pallets/mining_rewards.dart' as _i7; -import 'pallets/multisig.dart' as _i15; +import 'pallets/multisig.dart' as _i14; import 'pallets/preimage.dart' as _i8; import 'pallets/q_po_w.dart' as _i6; -import 'pallets/recovery.dart' as _i14; import 'pallets/reversible_transfers.dart' as _i10; import 'pallets/scheduler.dart' as _i9; import 'pallets/system.dart' as _i2; @@ -17,10 +16,10 @@ import 'pallets/tech_referenda.dart' as _i12; import 'pallets/timestamp.dart' as _i3; import 'pallets/transaction_payment.dart' as _i5; import 'pallets/treasury_pallet.dart' as _i13; -import 'pallets/utility.dart' as _i19; -import 'pallets/vesting.dart' as _i18; -import 'pallets/wormhole.dart' as _i16; -import 'pallets/zk_tree.dart' as _i17; +import 'pallets/utility.dart' as _i18; +import 'pallets/vesting.dart' as _i17; +import 'pallets/wormhole.dart' as _i15; +import 'pallets/zk_tree.dart' as _i16; class Queries { Queries(_i1.StateApi api) @@ -36,11 +35,10 @@ class Queries { techCollective = _i11.Queries(api), techReferenda = _i12.Queries(api), treasuryPallet = _i13.Queries(api), - recovery = _i14.Queries(api), - multisig = _i15.Queries(api), - wormhole = _i16.Queries(api), - zkTree = _i17.Queries(api), - vesting = _i18.Queries(api); + multisig = _i14.Queries(api), + wormhole = _i15.Queries(api), + zkTree = _i16.Queries(api), + vesting = _i17.Queries(api); final _i2.Queries system; @@ -66,15 +64,13 @@ class Queries { final _i13.Queries treasuryPallet; - final _i14.Queries recovery; + final _i14.Queries multisig; - final _i15.Queries multisig; + final _i15.Queries wormhole; - final _i16.Queries wormhole; + final _i16.Queries zkTree; - final _i17.Queries zkTree; - - final _i18.Queries vesting; + final _i17.Queries vesting; } class Extrinsics { @@ -88,7 +84,7 @@ class Extrinsics { final _i8.Txs preimage = _i8.Txs(); - final _i19.Txs utility = _i19.Txs(); + final _i18.Txs utility = _i18.Txs(); final _i10.Txs reversibleTransfers = _i10.Txs(); @@ -98,13 +94,11 @@ class Extrinsics { final _i13.Txs treasuryPallet = _i13.Txs(); - final _i14.Txs recovery = _i14.Txs(); - - final _i15.Txs multisig = _i15.Txs(); + final _i14.Txs multisig = _i14.Txs(); - final _i16.Txs wormhole = _i16.Txs(); + final _i15.Txs wormhole = _i15.Txs(); - final _i18.Txs vesting = _i18.Txs(); + final _i17.Txs vesting = _i17.Txs(); } class Constants { @@ -124,19 +118,17 @@ class Constants { final _i9.Constants scheduler = _i9.Constants(); - final _i19.Constants utility = _i19.Constants(); + final _i18.Constants utility = _i18.Constants(); final _i10.Constants reversibleTransfers = _i10.Constants(); final _i12.Constants techReferenda = _i12.Constants(); - final _i14.Constants recovery = _i14.Constants(); - - final _i15.Constants multisig = _i15.Constants(); + final _i14.Constants multisig = _i14.Constants(); - final _i16.Constants wormhole = _i16.Constants(); + final _i15.Constants wormhole = _i15.Constants(); - final _i18.Constants vesting = _i18.Constants(); + final _i17.Constants vesting = _i17.Constants(); } class Rpc { @@ -190,11 +182,11 @@ class Planck { final Registry registry; - _i20.Future connect() async { + _i19.Future connect() async { return await _provider.connect(); } - _i20.Future disconnect() async { + _i19.Future disconnect() async { return await _provider.disconnect(); } } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/call.dart b/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/call.dart index 0190e45b1..1677bfa65 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/call.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/call.dart @@ -2,11 +2,8 @@ import 'dart:typed_data' as _i2; import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i6; -import '../../sp_core/crypto/account_id32.dart' as _i4; import '../../sp_runtime/multiaddress/multi_address.dart' as _i3; -import '../types/adjustment_direction.dart' as _i5; /// Contains a variant per dispatchable extrinsic that this pallet has. abstract class Call { @@ -40,14 +37,6 @@ class $Call { return TransferAllowDeath(dest: dest, value: value); } - ForceTransfer forceTransfer({ - required _i3.MultiAddress source, - required _i3.MultiAddress dest, - required BigInt value, - }) { - return ForceTransfer(source: source, dest: dest, value: value); - } - TransferKeepAlive transferKeepAlive({required _i3.MultiAddress dest, required BigInt value}) { return TransferKeepAlive(dest: dest, value: value); } @@ -56,25 +45,6 @@ class $Call { return TransferAll(dest: dest, keepAlive: keepAlive); } - ForceUnreserve forceUnreserve({required _i3.MultiAddress who, required BigInt amount}) { - return ForceUnreserve(who: who, amount: amount); - } - - UpgradeAccounts upgradeAccounts({required List<_i4.AccountId32> who}) { - return UpgradeAccounts(who: who); - } - - ForceSetBalance forceSetBalance({required _i3.MultiAddress who, required BigInt newFree}) { - return ForceSetBalance(who: who, newFree: newFree); - } - - ForceAdjustTotalIssuance forceAdjustTotalIssuance({ - required _i5.AdjustmentDirection direction, - required BigInt delta, - }) { - return ForceAdjustTotalIssuance(direction: direction, delta: delta); - } - Burn burn({required BigInt value, required bool keepAlive}) { return Burn(value: value, keepAlive: keepAlive); } @@ -89,20 +59,10 @@ class $CallCodec with _i1.Codec { switch (index) { case 0: return TransferAllowDeath._decode(input); - case 2: - return ForceTransfer._decode(input); case 3: return TransferKeepAlive._decode(input); case 4: return TransferAll._decode(input); - case 5: - return ForceUnreserve._decode(input); - case 6: - return UpgradeAccounts._decode(input); - case 8: - return ForceSetBalance._decode(input); - case 9: - return ForceAdjustTotalIssuance._decode(input); case 10: return Burn._decode(input); default: @@ -116,27 +76,12 @@ class $CallCodec with _i1.Codec { case TransferAllowDeath: (value as TransferAllowDeath).encodeTo(output); break; - case ForceTransfer: - (value as ForceTransfer).encodeTo(output); - break; case TransferKeepAlive: (value as TransferKeepAlive).encodeTo(output); break; case TransferAll: (value as TransferAll).encodeTo(output); break; - case ForceUnreserve: - (value as ForceUnreserve).encodeTo(output); - break; - case UpgradeAccounts: - (value as UpgradeAccounts).encodeTo(output); - break; - case ForceSetBalance: - (value as ForceSetBalance).encodeTo(output); - break; - case ForceAdjustTotalIssuance: - (value as ForceAdjustTotalIssuance).encodeTo(output); - break; case Burn: (value as Burn).encodeTo(output); break; @@ -150,20 +95,10 @@ class $CallCodec with _i1.Codec { switch (value.runtimeType) { case TransferAllowDeath: return (value as TransferAllowDeath)._sizeHint(); - case ForceTransfer: - return (value as ForceTransfer)._sizeHint(); case TransferKeepAlive: return (value as TransferKeepAlive)._sizeHint(); case TransferAll: return (value as TransferAll)._sizeHint(); - case ForceUnreserve: - return (value as ForceUnreserve)._sizeHint(); - case UpgradeAccounts: - return (value as UpgradeAccounts)._sizeHint(); - case ForceSetBalance: - return (value as ForceSetBalance)._sizeHint(); - case ForceAdjustTotalIssuance: - return (value as ForceAdjustTotalIssuance)._sizeHint(); case Burn: return (value as Burn)._sizeHint(); default: @@ -221,57 +156,6 @@ class TransferAllowDeath extends Call { int get hashCode => Object.hash(dest, value); } -/// Exactly as `transfer_allow_death`, except the origin must be root and the source account -/// may be specified. -class ForceTransfer extends Call { - const ForceTransfer({required this.source, required this.dest, required this.value}); - - factory ForceTransfer._decode(_i1.Input input) { - return ForceTransfer( - source: _i3.MultiAddress.codec.decode(input), - dest: _i3.MultiAddress.codec.decode(input), - value: _i1.CompactBigIntCodec.codec.decode(input), - ); - } - - /// AccountIdLookupOf - final _i3.MultiAddress source; - - /// AccountIdLookupOf - final _i3.MultiAddress dest; - - /// T::Balance - final BigInt value; - - @override - Map> toJson() => { - 'force_transfer': {'source': source.toJson(), 'dest': dest.toJson(), 'value': value}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(source); - size = size + _i3.MultiAddress.codec.sizeHint(dest); - size = size + _i1.CompactBigIntCodec.codec.sizeHint(value); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(2, output); - _i3.MultiAddress.codec.encodeTo(source, output); - _i3.MultiAddress.codec.encodeTo(dest, output); - _i1.CompactBigIntCodec.codec.encodeTo(value, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is ForceTransfer && other.source == source && other.dest == dest && other.value == value; - - @override - int get hashCode => Object.hash(source, dest, value); -} - /// Same as the [`transfer_allow_death`] call, but with a check that the transfer will not /// kill the origin account. /// @@ -374,183 +258,6 @@ class TransferAll extends Call { int get hashCode => Object.hash(dest, keepAlive); } -/// Unreserve some balance from a user by force. -/// -/// Can only be called by ROOT. -class ForceUnreserve extends Call { - const ForceUnreserve({required this.who, required this.amount}); - - factory ForceUnreserve._decode(_i1.Input input) { - return ForceUnreserve(who: _i3.MultiAddress.codec.decode(input), amount: _i1.U128Codec.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress who; - - /// T::Balance - final BigInt amount; - - @override - Map> toJson() => { - 'force_unreserve': {'who': who.toJson(), 'amount': amount}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(who); - size = size + _i1.U128Codec.codec.sizeHint(amount); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(5, output); - _i3.MultiAddress.codec.encodeTo(who, output); - _i1.U128Codec.codec.encodeTo(amount, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is ForceUnreserve && other.who == who && other.amount == amount; - - @override - int get hashCode => Object.hash(who, amount); -} - -/// Upgrade a specified account. -/// -/// - `origin`: Must be `Signed`. -/// - `who`: The account to be upgraded. -/// -/// This will waive the transaction fee if at least all but 10% of the accounts needed to -/// be upgraded. (We let some not have to be upgraded just in order to allow for the -/// possibility of churn). -class UpgradeAccounts extends Call { - const UpgradeAccounts({required this.who}); - - factory UpgradeAccounts._decode(_i1.Input input) { - return UpgradeAccounts(who: const _i1.SequenceCodec<_i4.AccountId32>(_i4.AccountId32Codec()).decode(input)); - } - - /// Vec - final List<_i4.AccountId32> who; - - @override - Map>>> toJson() => { - 'upgrade_accounts': {'who': who.map((value) => value.toList()).toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i1.SequenceCodec<_i4.AccountId32>(_i4.AccountId32Codec()).sizeHint(who); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(6, output); - const _i1.SequenceCodec<_i4.AccountId32>(_i4.AccountId32Codec()).encodeTo(who, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is UpgradeAccounts && _i6.listsEqual(other.who, who); - - @override - int get hashCode => who.hashCode; -} - -/// Set the regular balance of a given account. -/// -/// The dispatch origin for this call is `root`. -class ForceSetBalance extends Call { - const ForceSetBalance({required this.who, required this.newFree}); - - factory ForceSetBalance._decode(_i1.Input input) { - return ForceSetBalance( - who: _i3.MultiAddress.codec.decode(input), - newFree: _i1.CompactBigIntCodec.codec.decode(input), - ); - } - - /// AccountIdLookupOf - final _i3.MultiAddress who; - - /// T::Balance - final BigInt newFree; - - @override - Map> toJson() => { - 'force_set_balance': {'who': who.toJson(), 'newFree': newFree}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(who); - size = size + _i1.CompactBigIntCodec.codec.sizeHint(newFree); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(8, output); - _i3.MultiAddress.codec.encodeTo(who, output); - _i1.CompactBigIntCodec.codec.encodeTo(newFree, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is ForceSetBalance && other.who == who && other.newFree == newFree; - - @override - int get hashCode => Object.hash(who, newFree); -} - -/// Adjust the total issuance in a saturating way. -/// -/// Can only be called by root and always needs a positive `delta`. -/// -/// # Example -class ForceAdjustTotalIssuance extends Call { - const ForceAdjustTotalIssuance({required this.direction, required this.delta}); - - factory ForceAdjustTotalIssuance._decode(_i1.Input input) { - return ForceAdjustTotalIssuance( - direction: _i5.AdjustmentDirection.codec.decode(input), - delta: _i1.CompactBigIntCodec.codec.decode(input), - ); - } - - /// AdjustmentDirection - final _i5.AdjustmentDirection direction; - - /// T::Balance - final BigInt delta; - - @override - Map> toJson() => { - 'force_adjust_total_issuance': {'direction': direction.toJson(), 'delta': delta}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i5.AdjustmentDirection.codec.sizeHint(direction); - size = size + _i1.CompactBigIntCodec.codec.sizeHint(delta); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(9, output); - _i5.AdjustmentDirection.codec.encodeTo(direction, output); - _i1.CompactBigIntCodec.codec.encodeTo(delta, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is ForceAdjustTotalIssuance && other.direction == direction && other.delta == delta; - - @override - int get hashCode => Object.hash(direction, delta); -} - /// Burn the specified liquid free balance from the origin account. /// /// If the origin's account ends up below the existential deposit as a result diff --git a/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/error.dart index 3cc28b4e6..e46b800f9 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/error.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/error.dart @@ -33,13 +33,7 @@ enum Error { tooManyHolds('TooManyHolds', 8), /// Number of freezes exceed `MaxFreezes`. - tooManyFreezes('TooManyFreezes', 9), - - /// The issuance cannot be modified since it is already deactivated. - issuanceDeactivated('IssuanceDeactivated', 10), - - /// The delta cannot be zero. - deltaZero('DeltaZero', 11); + tooManyFreezes('TooManyFreezes', 9); const Error(this.variantName, this.codecIndex); @@ -87,10 +81,6 @@ class $ErrorCodec with _i1.Codec { return Error.tooManyHolds; case 9: return Error.tooManyFreezes; - case 10: - return Error.issuanceDeactivated; - case 11: - return Error.deltaZero; default: throw Exception('Error: Invalid variant index: "$index"'); } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/event.dart b/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/event.dart index 565949dd1..13248bca3 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/event.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_balances/pallet/event.dart @@ -134,10 +134,6 @@ class $Event { return Thawed(who: who, amount: amount); } - TotalIssuanceForced totalIssuanceForced({required BigInt old, required BigInt new_}) { - return TotalIssuanceForced(old: old, new_: new_); - } - Held held({required _i5.RuntimeHoldReason reason, required _i3.AccountId32 who, required BigInt amount}) { return Held(reason: reason, who: who, amount: amount); } @@ -227,18 +223,16 @@ class $EventCodec with _i1.Codec { case 22: return Thawed._decode(input); case 23: - return TotalIssuanceForced._decode(input); - case 24: return Held._decode(input); - case 25: + case 24: return BurnedHeld._decode(input); - case 26: + case 25: return TransferOnHold._decode(input); - case 27: + case 26: return TransferAndHold._decode(input); - case 28: + case 27: return Released._decode(input); - case 29: + case 28: return Unexpected._decode(input); default: throw Exception('Event: Invalid variant index: "$index"'); @@ -317,9 +311,6 @@ class $EventCodec with _i1.Codec { case Thawed: (value as Thawed).encodeTo(output); break; - case TotalIssuanceForced: - (value as TotalIssuanceForced).encodeTo(output); - break; case Held: (value as Held).encodeTo(output); break; @@ -392,8 +383,6 @@ class $EventCodec with _i1.Codec { return (value as Frozen)._sizeHint(); case Thawed: return (value as Thawed)._sizeHint(); - case TotalIssuanceForced: - return (value as TotalIssuanceForced)._sizeHint(); case Held: return (value as Held)._sizeHint(); case BurnedHeld: @@ -1345,46 +1334,6 @@ class Thawed extends Event { int get hashCode => Object.hash(who, amount); } -/// The `TotalIssuance` was forcefully changed. -class TotalIssuanceForced extends Event { - const TotalIssuanceForced({required this.old, required this.new_}); - - factory TotalIssuanceForced._decode(_i1.Input input) { - return TotalIssuanceForced(old: _i1.U128Codec.codec.decode(input), new_: _i1.U128Codec.codec.decode(input)); - } - - /// T::Balance - final BigInt old; - - /// T::Balance - final BigInt new_; - - @override - Map> toJson() => { - 'TotalIssuanceForced': {'old': old, 'new': new_}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i1.U128Codec.codec.sizeHint(old); - size = size + _i1.U128Codec.codec.sizeHint(new_); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(23, output); - _i1.U128Codec.codec.encodeTo(old, output); - _i1.U128Codec.codec.encodeTo(new_, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is TotalIssuanceForced && other.old == old && other.new_ == new_; - - @override - int get hashCode => Object.hash(old, new_); -} - /// Some balance was placed on hold. class Held extends Event { const Held({required this.reason, required this.who, required this.amount}); @@ -1420,7 +1369,7 @@ class Held extends Event { } void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(24, output); + _i1.U8Codec.codec.encodeTo(23, output); _i5.RuntimeHoldReason.codec.encodeTo(reason, output); const _i1.U8ArrayCodec(32).encodeTo(who, output); _i1.U128Codec.codec.encodeTo(amount, output); @@ -1470,7 +1419,7 @@ class BurnedHeld extends Event { } void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(25, output); + _i1.U8Codec.codec.encodeTo(24, output); _i5.RuntimeHoldReason.codec.encodeTo(reason, output); const _i1.U8ArrayCodec(32).encodeTo(who, output); _i1.U128Codec.codec.encodeTo(amount, output); @@ -1525,7 +1474,7 @@ class TransferOnHold extends Event { } void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(26, output); + _i1.U8Codec.codec.encodeTo(25, output); _i5.RuntimeHoldReason.codec.encodeTo(reason, output); const _i1.U8ArrayCodec(32).encodeTo(source, output); const _i1.U8ArrayCodec(32).encodeTo(dest, output); @@ -1590,7 +1539,7 @@ class TransferAndHold extends Event { } void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(27, output); + _i1.U8Codec.codec.encodeTo(26, output); _i5.RuntimeHoldReason.codec.encodeTo(reason, output); const _i1.U8ArrayCodec(32).encodeTo(source, output); const _i1.U8ArrayCodec(32).encodeTo(dest, output); @@ -1645,7 +1594,7 @@ class Released extends Event { } void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(28, output); + _i1.U8Codec.codec.encodeTo(27, output); _i5.RuntimeHoldReason.codec.encodeTo(reason, output); const _i1.U8ArrayCodec(32).encodeTo(who, output); _i1.U128Codec.codec.encodeTo(amount, output); @@ -1681,7 +1630,7 @@ class Unexpected extends Event { } void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(29, output); + _i1.U8Codec.codec.encodeTo(28, output); _i6.UnexpectedKind.codec.encodeTo(value0, output); } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_balances/types/adjustment_direction.dart b/quantus_sdk/lib/generated/planck/types/pallet_balances/types/adjustment_direction.dart deleted file mode 100644 index 8e87929c4..000000000 --- a/quantus_sdk/lib/generated/planck/types/pallet_balances/types/adjustment_direction.dart +++ /dev/null @@ -1,49 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:typed_data' as _i2; - -import 'package:polkadart/scale_codec.dart' as _i1; - -enum AdjustmentDirection { - increase('Increase', 0), - decrease('Decrease', 1); - - const AdjustmentDirection(this.variantName, this.codecIndex); - - factory AdjustmentDirection.decode(_i1.Input input) { - return codec.decode(input); - } - - final String variantName; - - final int codecIndex; - - static const $AdjustmentDirectionCodec codec = $AdjustmentDirectionCodec(); - - String toJson() => variantName; - - _i2.Uint8List encode() { - return codec.encode(this); - } -} - -class $AdjustmentDirectionCodec with _i1.Codec { - const $AdjustmentDirectionCodec(); - - @override - AdjustmentDirection decode(_i1.Input input) { - final index = _i1.U8Codec.codec.decode(input); - switch (index) { - case 0: - return AdjustmentDirection.increase; - case 1: - return AdjustmentDirection.decrease; - default: - throw Exception('AdjustmentDirection: Invalid variant index: "$index"'); - } - } - - @override - void encodeTo(AdjustmentDirection value, _i1.Output output) { - _i1.U8Codec.codec.encodeTo(value.codecIndex, output); - } -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_mining_rewards/pallet/event.dart b/quantus_sdk/lib/generated/planck/types/pallet_mining_rewards/pallet/event.dart index 7ced4035b..20a278435 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_mining_rewards/pallet/event.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_mining_rewards/pallet/event.dart @@ -42,16 +42,12 @@ class $Event { return FeesCollected(amount: amount, total: total); } - TreasuryRewarded treasuryRewarded({required BigInt reward}) { - return TreasuryRewarded(reward: reward); + PayoutDeferred payoutDeferred({required BigInt amount}) { + return PayoutDeferred(amount: amount); } - MinerRewardRedirected minerRewardRedirected({required _i3.AccountId32 miner, required BigInt reward}) { - return MinerRewardRedirected(miner: miner, reward: reward); - } - - TreasuryMintFailed treasuryMintFailed({required BigInt reward}) { - return TreasuryMintFailed(reward: reward); + MinerMintFailed minerMintFailed({required _i3.AccountId32 miner, required BigInt reward}) { + return MinerMintFailed(miner: miner, reward: reward); } } @@ -67,11 +63,9 @@ class $EventCodec with _i1.Codec { case 1: return FeesCollected._decode(input); case 2: - return TreasuryRewarded._decode(input); + return PayoutDeferred._decode(input); case 3: - return MinerRewardRedirected._decode(input); - case 4: - return TreasuryMintFailed._decode(input); + return MinerMintFailed._decode(input); default: throw Exception('Event: Invalid variant index: "$index"'); } @@ -86,14 +80,11 @@ class $EventCodec with _i1.Codec { case FeesCollected: (value as FeesCollected).encodeTo(output); break; - case TreasuryRewarded: - (value as TreasuryRewarded).encodeTo(output); - break; - case MinerRewardRedirected: - (value as MinerRewardRedirected).encodeTo(output); + case PayoutDeferred: + (value as PayoutDeferred).encodeTo(output); break; - case TreasuryMintFailed: - (value as TreasuryMintFailed).encodeTo(output); + case MinerMintFailed: + (value as MinerMintFailed).encodeTo(output); break; default: throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); @@ -107,12 +98,10 @@ class $EventCodec with _i1.Codec { return (value as MinerRewarded)._sizeHint(); case FeesCollected: return (value as FeesCollected)._sizeHint(); - case TreasuryRewarded: - return (value as TreasuryRewarded)._sizeHint(); - case MinerRewardRedirected: - return (value as MinerRewardRedirected)._sizeHint(); - case TreasuryMintFailed: - return (value as TreasuryMintFailed)._sizeHint(); + case PayoutDeferred: + return (value as PayoutDeferred)._sizeHint(); + case MinerMintFailed: + return (value as MinerMintFailed)._sizeHint(); default: throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); } @@ -132,7 +121,7 @@ class MinerRewarded extends Event { final _i3.AccountId32 miner; /// BalanceOf - /// Total reward (base + fees) + /// Quantized reward (block reward + fees, aligned to the wormhole quantum) final BigInt reward; @override @@ -203,50 +192,47 @@ class FeesCollected extends Event { int get hashCode => Object.hash(amount, total); } -/// Rewards were sent to Treasury when no miner was specified -class TreasuryRewarded extends Event { - const TreasuryRewarded({required this.reward}); +/// No miner in the digest; the credit stays in [`CollectedFees`] for the next block. +class PayoutDeferred extends Event { + const PayoutDeferred({required this.amount}); - factory TreasuryRewarded._decode(_i1.Input input) { - return TreasuryRewarded(reward: _i1.U128Codec.codec.decode(input)); + factory PayoutDeferred._decode(_i1.Input input) { + return PayoutDeferred(amount: _i1.U128Codec.codec.decode(input)); } /// BalanceOf - /// Total reward (base + fees) - final BigInt reward; + /// Amount held for the next miner + final BigInt amount; @override Map> toJson() => { - 'TreasuryRewarded': {'reward': reward}, + 'PayoutDeferred': {'amount': amount}, }; int _sizeHint() { int size = 1; - size = size + _i1.U128Codec.codec.sizeHint(reward); + size = size + _i1.U128Codec.codec.sizeHint(amount); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(2, output); - _i1.U128Codec.codec.encodeTo(reward, output); + _i1.U128Codec.codec.encodeTo(amount, output); } @override - bool operator ==(Object other) => identical(this, other) || other is TreasuryRewarded && other.reward == reward; + bool operator ==(Object other) => identical(this, other) || other is PayoutDeferred && other.amount == amount; @override - int get hashCode => reward.hashCode; + int get hashCode => amount.hashCode; } -/// Miner reward was redirected to treasury due to mint failure -class MinerRewardRedirected extends Event { - const MinerRewardRedirected({required this.miner, required this.reward}); +/// Miner mint failed; the credit stays in [`CollectedFees`] for retry. +class MinerMintFailed extends Event { + const MinerMintFailed({required this.miner, required this.reward}); - factory MinerRewardRedirected._decode(_i1.Input input) { - return MinerRewardRedirected( - miner: const _i1.U8ArrayCodec(32).decode(input), - reward: _i1.U128Codec.codec.decode(input), - ); + factory MinerMintFailed._decode(_i1.Input input) { + return MinerMintFailed(miner: const _i1.U8ArrayCodec(32).decode(input), reward: _i1.U128Codec.codec.decode(input)); } /// T::AccountId @@ -254,12 +240,12 @@ class MinerRewardRedirected extends Event { final _i3.AccountId32 miner; /// BalanceOf - /// The reward amount redirected to treasury + /// The reward amount retained final BigInt reward; @override Map> toJson() => { - 'MinerRewardRedirected': {'miner': miner.toList(), 'reward': reward}, + 'MinerMintFailed': {'miner': miner.toList(), 'reward': reward}, }; int _sizeHint() { @@ -278,43 +264,8 @@ class MinerRewardRedirected extends Event { @override bool operator ==(Object other) => identical(this, other) || - other is MinerRewardRedirected && _i4.listsEqual(other.miner, miner) && other.reward == reward; + other is MinerMintFailed && _i4.listsEqual(other.miner, miner) && other.reward == reward; @override int get hashCode => Object.hash(miner, reward); } - -/// Treasury mint failed; amount retained in [`CollectedFees`] for retry. -class TreasuryMintFailed extends Event { - const TreasuryMintFailed({required this.reward}); - - factory TreasuryMintFailed._decode(_i1.Input input) { - return TreasuryMintFailed(reward: _i1.U128Codec.codec.decode(input)); - } - - /// BalanceOf - /// The reward amount that failed to mint - final BigInt reward; - - @override - Map> toJson() => { - 'TreasuryMintFailed': {'reward': reward}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i1.U128Codec.codec.sizeHint(reward); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(4, output); - _i1.U128Codec.codec.encodeTo(reward, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is TreasuryMintFailed && other.reward == reward; - - @override - int get hashCode => reward.hashCode; -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/call.dart b/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/call.dart index 3b95493ea..ee8d65a4b 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/call.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/call.dart @@ -2,8 +2,9 @@ import 'dart:typed_data' as _i2; import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i4; +import 'package:quiver/collection.dart' as _i5; +import '../../quantus_runtime/runtime_call.dart' as _i4; import '../../sp_core/crypto/account_id32.dart' as _i3; /// Contains a variant per dispatchable extrinsic that this pallet has. @@ -62,8 +63,8 @@ class $Call { return ClaimDeposits(multisigAddress: multisigAddress); } - Execute execute({required _i3.AccountId32 multisigAddress, required int proposalId}) { - return Execute(multisigAddress: multisigAddress, proposalId: proposalId); + Execute execute({required _i3.AccountId32 multisigAddress, required int proposalId, required _i4.RuntimeCall call}) { + return Execute(multisigAddress: multisigAddress, proposalId: proposalId, call: call); } } @@ -155,7 +156,8 @@ class $CallCodec with _i1.Codec { /// The multisig address is deterministically derived from: /// hash(pallet_id || sorted_signers || threshold || nonce) /// -/// Signers are automatically sorted before hashing, so order doesn't matter. +/// Signers are sorted before hashing, so order doesn't matter. +/// Duplicate accounts are rejected. /// /// Economic costs: /// - MultisigFee: burned immediately (spam prevention) @@ -207,7 +209,7 @@ class CreateMultisig extends Call { bool operator ==(Object other) => identical(this, other) || other is CreateMultisig && - _i4.listsEqual(other.signers, signers) && + _i5.listsEqual(other.signers, signers) && other.threshold == threshold && other.nonce == nonce; @@ -278,8 +280,8 @@ class Propose extends Call { bool operator ==(Object other) => identical(this, other) || other is Propose && - _i4.listsEqual(other.multisigAddress, multisigAddress) && - _i4.listsEqual(other.call, call) && + _i5.listsEqual(other.multisigAddress, multisigAddress) && + _i5.listsEqual(other.call, call) && other.expiry == expiry; @override @@ -347,9 +349,9 @@ class Approve extends Call { bool operator ==(Object other) => identical(this, other) || other is Approve && - _i4.listsEqual(other.multisigAddress, multisigAddress) && + _i5.listsEqual(other.multisigAddress, multisigAddress) && other.proposalId == proposalId && - _i4.listsEqual(other.call, call); + _i5.listsEqual(other.call, call); @override int get hashCode => Object.hash(multisigAddress, proposalId, call); @@ -397,7 +399,7 @@ class Cancel extends Call { @override bool operator ==(Object other) => identical(this, other) || - other is Cancel && _i4.listsEqual(other.multisigAddress, multisigAddress) && other.proposalId == proposalId; + other is Cancel && _i5.listsEqual(other.multisigAddress, multisigAddress) && other.proposalId == proposalId; @override int get hashCode => Object.hash(multisigAddress, proposalId); @@ -452,7 +454,7 @@ class RemoveExpired extends Call { bool operator ==(Object other) => identical(this, other) || other is RemoveExpired && - _i4.listsEqual(other.multisigAddress, multisigAddress) && + _i5.listsEqual(other.multisigAddress, multisigAddress) && other.proposalId == proposalId; @override @@ -497,7 +499,7 @@ class ClaimDeposits extends Call { @override bool operator ==(Object other) => - identical(this, other) || other is ClaimDeposits && _i4.listsEqual(other.multisigAddress, multisigAddress); + identical(this, other) || other is ClaimDeposits && _i5.listsEqual(other.multisigAddress, multisigAddress); @override int get hashCode => multisigAddress.hashCode; @@ -508,25 +510,37 @@ class ClaimDeposits extends Call { /// Can be called by any signer of the multisig once the proposal has reached /// the approval threshold (status = Approved). The proposal must not be expired. /// +/// The executor resubmits the proposal's inner call; execution proceeds only +/// if it is byte-equal to the payload stored at `proposal_id` — the same +/// binding `approve` enforces. This serves two purposes: +/// - **Clearsigning:** the executor's (hardware) wallet displays and signs the actual call +/// being dispatched, not an opaque proposal id. +/// - **Self-describing weight:** the executing extrinsic carries the inner call, so its +/// declared weight carries the inner call's own declared weight (refunded to actuals +/// post-dispatch) instead of reserving a flat `MaxInnerCallWeight`, and runtime +/// transaction extensions can inspect the inner call and price its side effects +/// (account-reap cleanup, transfer-proof recording) exactly as they do for directly +/// submitted calls. Nothing about the dispatch is invisible to pre-dispatch admission or +/// fees. (Only the bookkeeping term is reserved at `MaxCallSize`, since the stored bytes' +/// length is unknown pre-dispatch; the unused remainder is refunded.) +/// /// On execution: -/// - The call is decoded and dispatched as the multisig account +/// - The call is dispatched as the multisig account /// - Proposal is removed from storage /// - Deposit is returned to the proposer /// /// Parameters: /// - `multisig_address`: The multisig account /// - `proposal_id`: ID (nonce) of the proposal to execute -/// -/// Note: The weight charged includes both multisig bookkeeping and MaxInnerCallWeight. -/// Actual weight is refunded based on the inner call's post-dispatch info. -/// The inner call's weight is validated against MaxInnerCallWeight at propose time. +/// - `call`: The proposal's inner call, byte-equal to the stored payload class Execute extends Call { - const Execute({required this.multisigAddress, required this.proposalId}); + const Execute({required this.multisigAddress, required this.proposalId, required this.call}); factory Execute._decode(_i1.Input input) { return Execute( multisigAddress: const _i1.U8ArrayCodec(32).decode(input), proposalId: _i1.U32Codec.codec.decode(input), + call: _i4.RuntimeCall.codec.decode(input), ); } @@ -536,15 +550,19 @@ class Execute extends Call { /// u32 final int proposalId; + /// Box<::RuntimeCall> + final _i4.RuntimeCall call; + @override Map> toJson() => { - 'execute': {'multisigAddress': multisigAddress.toList(), 'proposalId': proposalId}, + 'execute': {'multisigAddress': multisigAddress.toList(), 'proposalId': proposalId, 'call': call.toJson()}, }; int _sizeHint() { int size = 1; size = size + const _i3.AccountId32Codec().sizeHint(multisigAddress); size = size + _i1.U32Codec.codec.sizeHint(proposalId); + size = size + _i4.RuntimeCall.codec.sizeHint(call); return size; } @@ -552,13 +570,17 @@ class Execute extends Call { _i1.U8Codec.codec.encodeTo(6, output); const _i1.U8ArrayCodec(32).encodeTo(multisigAddress, output); _i1.U32Codec.codec.encodeTo(proposalId, output); + _i4.RuntimeCall.codec.encodeTo(call, output); } @override bool operator ==(Object other) => identical(this, other) || - other is Execute && _i4.listsEqual(other.multisigAddress, multisigAddress) && other.proposalId == proposalId; + other is Execute && + _i5.listsEqual(other.multisigAddress, multisigAddress) && + other.proposalId == proposalId && + other.call == call; @override - int get hashCode => Object.hash(multisigAddress, proposalId); + int get hashCode => Object.hash(multisigAddress, proposalId, call); } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/error.dart index 0522492b8..a4ae65acc 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/error.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_multisig/pallet/error.dart @@ -82,7 +82,10 @@ enum Error { callWeightExceedsLimit('CallWeightExceedsLimit', 24), /// Provided call does not match the stored proposal payload - callMismatch('CallMismatch', 25); + callMismatch('CallMismatch', 25), + + /// Signer list contains the same account more than once + duplicateSigners('DuplicateSigners', 26); const Error(this.variantName, this.codecIndex); @@ -162,6 +165,8 @@ class $ErrorCodec with _i1.Codec { return Error.callWeightExceedsLimit; case 25: return Error.callMismatch; + case 26: + return Error.duplicateSigners; default: throw Exception('Error: Invalid variant index: "$index"'); } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_recovery/active_recovery.dart b/quantus_sdk/lib/generated/planck/types/pallet_recovery/active_recovery.dart deleted file mode 100644 index 2df5af34d..000000000 --- a/quantus_sdk/lib/generated/planck/types/pallet_recovery/active_recovery.dart +++ /dev/null @@ -1,76 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:typed_data' as _i3; - -import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i4; - -import '../sp_core/crypto/account_id32.dart' as _i2; - -class ActiveRecovery { - const ActiveRecovery({required this.created, required this.deposit, required this.friends}); - - factory ActiveRecovery.decode(_i1.Input input) { - return codec.decode(input); - } - - /// BlockNumber - final int created; - - /// Balance - final BigInt deposit; - - /// Friends - final List<_i2.AccountId32> friends; - - static const $ActiveRecoveryCodec codec = $ActiveRecoveryCodec(); - - _i3.Uint8List encode() { - return codec.encode(this); - } - - Map toJson() => { - 'created': created, - 'deposit': deposit, - 'friends': friends.map((value) => value.toList()).toList(), - }; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is ActiveRecovery && - other.created == created && - other.deposit == deposit && - _i4.listsEqual(other.friends, friends); - - @override - int get hashCode => Object.hash(created, deposit, friends); -} - -class $ActiveRecoveryCodec with _i1.Codec { - const $ActiveRecoveryCodec(); - - @override - void encodeTo(ActiveRecovery obj, _i1.Output output) { - _i1.U32Codec.codec.encodeTo(obj.created, output); - _i1.U128Codec.codec.encodeTo(obj.deposit, output); - const _i1.SequenceCodec<_i2.AccountId32>(_i2.AccountId32Codec()).encodeTo(obj.friends, output); - } - - @override - ActiveRecovery decode(_i1.Input input) { - return ActiveRecovery( - created: _i1.U32Codec.codec.decode(input), - deposit: _i1.U128Codec.codec.decode(input), - friends: const _i1.SequenceCodec<_i2.AccountId32>(_i2.AccountId32Codec()).decode(input), - ); - } - - @override - int sizeHint(ActiveRecovery obj) { - int size = 0; - size = size + _i1.U32Codec.codec.sizeHint(obj.created); - size = size + _i1.U128Codec.codec.sizeHint(obj.deposit); - size = size + const _i1.SequenceCodec<_i2.AccountId32>(_i2.AccountId32Codec()).sizeHint(obj.friends); - return size; - } -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_recovery/deposit_kind.dart b/quantus_sdk/lib/generated/planck/types/pallet_recovery/deposit_kind.dart deleted file mode 100644 index 8e0a6d10e..000000000 --- a/quantus_sdk/lib/generated/planck/types/pallet_recovery/deposit_kind.dart +++ /dev/null @@ -1,135 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:typed_data' as _i2; - -import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i4; - -import '../sp_core/crypto/account_id32.dart' as _i3; - -abstract class DepositKind { - const DepositKind(); - - factory DepositKind.decode(_i1.Input input) { - return codec.decode(input); - } - - static const $DepositKindCodec codec = $DepositKindCodec(); - - static const $DepositKind values = $DepositKind(); - - _i2.Uint8List encode() { - final output = _i1.ByteOutput(codec.sizeHint(this)); - codec.encodeTo(this, output); - return output.toBytes(); - } - - int sizeHint() { - return codec.sizeHint(this); - } - - Map toJson(); -} - -class $DepositKind { - const $DepositKind(); - - RecoveryConfig recoveryConfig() { - return RecoveryConfig(); - } - - ActiveRecoveryFor activeRecoveryFor(_i3.AccountId32 value0) { - return ActiveRecoveryFor(value0); - } -} - -class $DepositKindCodec with _i1.Codec { - const $DepositKindCodec(); - - @override - DepositKind decode(_i1.Input input) { - final index = _i1.U8Codec.codec.decode(input); - switch (index) { - case 0: - return const RecoveryConfig(); - case 1: - return ActiveRecoveryFor._decode(input); - default: - throw Exception('DepositKind: Invalid variant index: "$index"'); - } - } - - @override - void encodeTo(DepositKind value, _i1.Output output) { - switch (value.runtimeType) { - case RecoveryConfig: - (value as RecoveryConfig).encodeTo(output); - break; - case ActiveRecoveryFor: - (value as ActiveRecoveryFor).encodeTo(output); - break; - default: - throw Exception('DepositKind: Unsupported "$value" of type "${value.runtimeType}"'); - } - } - - @override - int sizeHint(DepositKind value) { - switch (value.runtimeType) { - case RecoveryConfig: - return 1; - case ActiveRecoveryFor: - return (value as ActiveRecoveryFor)._sizeHint(); - default: - throw Exception('DepositKind: Unsupported "$value" of type "${value.runtimeType}"'); - } - } -} - -class RecoveryConfig extends DepositKind { - const RecoveryConfig(); - - @override - Map toJson() => {'RecoveryConfig': null}; - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(0, output); - } - - @override - bool operator ==(Object other) => other is RecoveryConfig; - - @override - int get hashCode => runtimeType.hashCode; -} - -class ActiveRecoveryFor extends DepositKind { - const ActiveRecoveryFor(this.value0); - - factory ActiveRecoveryFor._decode(_i1.Input input) { - return ActiveRecoveryFor(const _i1.U8ArrayCodec(32).decode(input)); - } - - /// ::AccountId - final _i3.AccountId32 value0; - - @override - Map> toJson() => {'ActiveRecoveryFor': value0.toList()}; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(value0); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(1, output); - const _i1.U8ArrayCodec(32).encodeTo(value0, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is ActiveRecoveryFor && _i4.listsEqual(other.value0, value0); - - @override - int get hashCode => value0.hashCode; -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/call.dart b/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/call.dart deleted file mode 100644 index 6aa962cbd..000000000 --- a/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/call.dart +++ /dev/null @@ -1,653 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:typed_data' as _i2; - -import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i6; - -import '../../quantus_runtime/runtime_call.dart' as _i4; -import '../../sp_core/crypto/account_id32.dart' as _i5; -import '../../sp_runtime/multiaddress/multi_address.dart' as _i3; - -/// Contains a variant per dispatchable extrinsic that this pallet has. -abstract class Call { - const Call(); - - factory Call.decode(_i1.Input input) { - return codec.decode(input); - } - - static const $CallCodec codec = $CallCodec(); - - static const $Call values = $Call(); - - _i2.Uint8List encode() { - final output = _i1.ByteOutput(codec.sizeHint(this)); - codec.encodeTo(this, output); - return output.toBytes(); - } - - int sizeHint() { - return codec.sizeHint(this); - } - - Map toJson(); -} - -class $Call { - const $Call(); - - AsRecovered asRecovered({required _i3.MultiAddress account, required _i4.RuntimeCall call}) { - return AsRecovered(account: account, call: call); - } - - SetRecovered setRecovered({required _i3.MultiAddress lost, required _i3.MultiAddress rescuer}) { - return SetRecovered(lost: lost, rescuer: rescuer); - } - - CreateRecovery createRecovery({ - required List<_i5.AccountId32> friends, - required int threshold, - required int delayPeriod, - }) { - return CreateRecovery(friends: friends, threshold: threshold, delayPeriod: delayPeriod); - } - - InitiateRecovery initiateRecovery({required _i3.MultiAddress account}) { - return InitiateRecovery(account: account); - } - - VouchRecovery vouchRecovery({required _i3.MultiAddress lost, required _i3.MultiAddress rescuer}) { - return VouchRecovery(lost: lost, rescuer: rescuer); - } - - ClaimRecovery claimRecovery({required _i3.MultiAddress account}) { - return ClaimRecovery(account: account); - } - - CloseRecovery closeRecovery({required _i3.MultiAddress rescuer}) { - return CloseRecovery(rescuer: rescuer); - } - - RemoveRecovery removeRecovery() { - return RemoveRecovery(); - } - - CancelRecovered cancelRecovered({required _i3.MultiAddress account}) { - return CancelRecovered(account: account); - } - - PokeDeposit pokeDeposit({_i3.MultiAddress? maybeAccount}) { - return PokeDeposit(maybeAccount: maybeAccount); - } -} - -class $CallCodec with _i1.Codec { - const $CallCodec(); - - @override - Call decode(_i1.Input input) { - final index = _i1.U8Codec.codec.decode(input); - switch (index) { - case 0: - return AsRecovered._decode(input); - case 1: - return SetRecovered._decode(input); - case 2: - return CreateRecovery._decode(input); - case 3: - return InitiateRecovery._decode(input); - case 4: - return VouchRecovery._decode(input); - case 5: - return ClaimRecovery._decode(input); - case 6: - return CloseRecovery._decode(input); - case 7: - return const RemoveRecovery(); - case 8: - return CancelRecovered._decode(input); - case 9: - return PokeDeposit._decode(input); - default: - throw Exception('Call: Invalid variant index: "$index"'); - } - } - - @override - void encodeTo(Call value, _i1.Output output) { - switch (value.runtimeType) { - case AsRecovered: - (value as AsRecovered).encodeTo(output); - break; - case SetRecovered: - (value as SetRecovered).encodeTo(output); - break; - case CreateRecovery: - (value as CreateRecovery).encodeTo(output); - break; - case InitiateRecovery: - (value as InitiateRecovery).encodeTo(output); - break; - case VouchRecovery: - (value as VouchRecovery).encodeTo(output); - break; - case ClaimRecovery: - (value as ClaimRecovery).encodeTo(output); - break; - case CloseRecovery: - (value as CloseRecovery).encodeTo(output); - break; - case RemoveRecovery: - (value as RemoveRecovery).encodeTo(output); - break; - case CancelRecovered: - (value as CancelRecovered).encodeTo(output); - break; - case PokeDeposit: - (value as PokeDeposit).encodeTo(output); - break; - default: - throw Exception('Call: Unsupported "$value" of type "${value.runtimeType}"'); - } - } - - @override - int sizeHint(Call value) { - switch (value.runtimeType) { - case AsRecovered: - return (value as AsRecovered)._sizeHint(); - case SetRecovered: - return (value as SetRecovered)._sizeHint(); - case CreateRecovery: - return (value as CreateRecovery)._sizeHint(); - case InitiateRecovery: - return (value as InitiateRecovery)._sizeHint(); - case VouchRecovery: - return (value as VouchRecovery)._sizeHint(); - case ClaimRecovery: - return (value as ClaimRecovery)._sizeHint(); - case CloseRecovery: - return (value as CloseRecovery)._sizeHint(); - case RemoveRecovery: - return 1; - case CancelRecovered: - return (value as CancelRecovered)._sizeHint(); - case PokeDeposit: - return (value as PokeDeposit)._sizeHint(); - default: - throw Exception('Call: Unsupported "$value" of type "${value.runtimeType}"'); - } - } -} - -/// Send a call through a recovered account. -/// -/// The dispatch origin for this call must be _Signed_ and registered to -/// be able to make calls on behalf of the recovered account. -/// -/// Parameters: -/// - `account`: The recovered account you want to make a call on-behalf-of. -/// - `call`: The call you want to make with the recovered account. -class AsRecovered extends Call { - const AsRecovered({required this.account, required this.call}); - - factory AsRecovered._decode(_i1.Input input) { - return AsRecovered(account: _i3.MultiAddress.codec.decode(input), call: _i4.RuntimeCall.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress account; - - /// Box<::RuntimeCall> - final _i4.RuntimeCall call; - - @override - Map>> toJson() => { - 'as_recovered': {'account': account.toJson(), 'call': call.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(account); - size = size + _i4.RuntimeCall.codec.sizeHint(call); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(0, output); - _i3.MultiAddress.codec.encodeTo(account, output); - _i4.RuntimeCall.codec.encodeTo(call, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is AsRecovered && other.account == account && other.call == call; - - @override - int get hashCode => Object.hash(account, call); -} - -/// Allow ROOT to bypass the recovery process and set a rescuer account -/// for a lost account directly. -/// -/// The dispatch origin for this call must be _ROOT_. -/// -/// Parameters: -/// - `lost`: The "lost account" to be recovered. -/// - `rescuer`: The "rescuer account" which can call as the lost account. -class SetRecovered extends Call { - const SetRecovered({required this.lost, required this.rescuer}); - - factory SetRecovered._decode(_i1.Input input) { - return SetRecovered(lost: _i3.MultiAddress.codec.decode(input), rescuer: _i3.MultiAddress.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress lost; - - /// AccountIdLookupOf - final _i3.MultiAddress rescuer; - - @override - Map>> toJson() => { - 'set_recovered': {'lost': lost.toJson(), 'rescuer': rescuer.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(lost); - size = size + _i3.MultiAddress.codec.sizeHint(rescuer); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(1, output); - _i3.MultiAddress.codec.encodeTo(lost, output); - _i3.MultiAddress.codec.encodeTo(rescuer, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is SetRecovered && other.lost == lost && other.rescuer == rescuer; - - @override - int get hashCode => Object.hash(lost, rescuer); -} - -/// Create a recovery configuration for your account. This makes your account recoverable. -/// -/// Payment: `ConfigDepositBase` + `FriendDepositFactor` * #_of_friends balance -/// will be reserved for storing the recovery configuration. This deposit is returned -/// in full when the user calls `remove_recovery`. -/// -/// The dispatch origin for this call must be _Signed_. -/// -/// Parameters: -/// - `friends`: A list of friends you trust to vouch for recovery attempts. Should be -/// ordered and contain no duplicate values. -/// - `threshold`: The number of friends that must vouch for a recovery attempt before the -/// account can be recovered. Should be less than or equal to the length of the list of -/// friends. -/// - `delay_period`: The number of blocks after a recovery attempt is initialized that -/// needs to pass before the account can be recovered. -class CreateRecovery extends Call { - const CreateRecovery({required this.friends, required this.threshold, required this.delayPeriod}); - - factory CreateRecovery._decode(_i1.Input input) { - return CreateRecovery( - friends: const _i1.SequenceCodec<_i5.AccountId32>(_i5.AccountId32Codec()).decode(input), - threshold: _i1.U16Codec.codec.decode(input), - delayPeriod: _i1.U32Codec.codec.decode(input), - ); - } - - /// Vec - final List<_i5.AccountId32> friends; - - /// u16 - final int threshold; - - /// BlockNumberFromProviderOf - final int delayPeriod; - - @override - Map> toJson() => { - 'create_recovery': { - 'friends': friends.map((value) => value.toList()).toList(), - 'threshold': threshold, - 'delayPeriod': delayPeriod, - }, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i1.SequenceCodec<_i5.AccountId32>(_i5.AccountId32Codec()).sizeHint(friends); - size = size + _i1.U16Codec.codec.sizeHint(threshold); - size = size + _i1.U32Codec.codec.sizeHint(delayPeriod); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(2, output); - const _i1.SequenceCodec<_i5.AccountId32>(_i5.AccountId32Codec()).encodeTo(friends, output); - _i1.U16Codec.codec.encodeTo(threshold, output); - _i1.U32Codec.codec.encodeTo(delayPeriod, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is CreateRecovery && - _i6.listsEqual(other.friends, friends) && - other.threshold == threshold && - other.delayPeriod == delayPeriod; - - @override - int get hashCode => Object.hash(friends, threshold, delayPeriod); -} - -/// Initiate the process for recovering a recoverable account. -/// -/// Payment: `RecoveryDeposit` balance will be reserved for initiating the -/// recovery process. This deposit will always be repatriated to the account -/// trying to be recovered. See `close_recovery`. -/// -/// The dispatch origin for this call must be _Signed_. -/// -/// Parameters: -/// - `account`: The lost account that you want to recover. This account needs to be -/// recoverable (i.e. have a recovery configuration). -class InitiateRecovery extends Call { - const InitiateRecovery({required this.account}); - - factory InitiateRecovery._decode(_i1.Input input) { - return InitiateRecovery(account: _i3.MultiAddress.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress account; - - @override - Map>> toJson() => { - 'initiate_recovery': {'account': account.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(account); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(3, output); - _i3.MultiAddress.codec.encodeTo(account, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is InitiateRecovery && other.account == account; - - @override - int get hashCode => account.hashCode; -} - -/// Allow a "friend" of a recoverable account to vouch for an active recovery -/// process for that account. -/// -/// The dispatch origin for this call must be _Signed_ and must be a "friend" -/// for the recoverable account. -/// -/// Parameters: -/// - `lost`: The lost account that you want to recover. -/// - `rescuer`: The account trying to rescue the lost account that you want to vouch for. -/// -/// The combination of these two parameters must point to an active recovery -/// process. -class VouchRecovery extends Call { - const VouchRecovery({required this.lost, required this.rescuer}); - - factory VouchRecovery._decode(_i1.Input input) { - return VouchRecovery(lost: _i3.MultiAddress.codec.decode(input), rescuer: _i3.MultiAddress.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress lost; - - /// AccountIdLookupOf - final _i3.MultiAddress rescuer; - - @override - Map>> toJson() => { - 'vouch_recovery': {'lost': lost.toJson(), 'rescuer': rescuer.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(lost); - size = size + _i3.MultiAddress.codec.sizeHint(rescuer); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(4, output); - _i3.MultiAddress.codec.encodeTo(lost, output); - _i3.MultiAddress.codec.encodeTo(rescuer, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is VouchRecovery && other.lost == lost && other.rescuer == rescuer; - - @override - int get hashCode => Object.hash(lost, rescuer); -} - -/// Allow a successful rescuer to claim their recovered account. -/// -/// The dispatch origin for this call must be _Signed_ and must be a "rescuer" -/// who has successfully completed the account recovery process: collected -/// `threshold` or more vouches, waited `delay_period` blocks since initiation. -/// -/// Parameters: -/// - `account`: The lost account that you want to claim has been successfully recovered by -/// you. -class ClaimRecovery extends Call { - const ClaimRecovery({required this.account}); - - factory ClaimRecovery._decode(_i1.Input input) { - return ClaimRecovery(account: _i3.MultiAddress.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress account; - - @override - Map>> toJson() => { - 'claim_recovery': {'account': account.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(account); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(5, output); - _i3.MultiAddress.codec.encodeTo(account, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is ClaimRecovery && other.account == account; - - @override - int get hashCode => account.hashCode; -} - -/// As the controller of a recoverable account, close an active recovery -/// process for your account. -/// -/// Payment: By calling this function, the recoverable account will receive -/// the recovery deposit `RecoveryDeposit` placed by the rescuer. -/// -/// The dispatch origin for this call must be _Signed_ and must be a -/// recoverable account with an active recovery process for it. -/// -/// Parameters: -/// - `rescuer`: The account trying to rescue this recoverable account. -class CloseRecovery extends Call { - const CloseRecovery({required this.rescuer}); - - factory CloseRecovery._decode(_i1.Input input) { - return CloseRecovery(rescuer: _i3.MultiAddress.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress rescuer; - - @override - Map>> toJson() => { - 'close_recovery': {'rescuer': rescuer.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(rescuer); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(6, output); - _i3.MultiAddress.codec.encodeTo(rescuer, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is CloseRecovery && other.rescuer == rescuer; - - @override - int get hashCode => rescuer.hashCode; -} - -/// Remove the recovery process for your account. Recovered accounts are still accessible. -/// -/// NOTE: The user must make sure to call `close_recovery` on all active -/// recovery attempts before calling this function else it will fail. -/// -/// Payment: By calling this function the recoverable account will unreserve -/// their recovery configuration deposit. -/// (`ConfigDepositBase` + `FriendDepositFactor` * #_of_friends) -/// -/// The dispatch origin for this call must be _Signed_ and must be a -/// recoverable account (i.e. has a recovery configuration). -class RemoveRecovery extends Call { - const RemoveRecovery(); - - @override - Map toJson() => {'remove_recovery': null}; - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(7, output); - } - - @override - bool operator ==(Object other) => other is RemoveRecovery; - - @override - int get hashCode => runtimeType.hashCode; -} - -/// Cancel the ability to use `as_recovered` for `account`. -/// -/// The dispatch origin for this call must be _Signed_ and registered to -/// be able to make calls on behalf of the recovered account. -/// -/// Parameters: -/// - `account`: The recovered account you are able to call on-behalf-of. -class CancelRecovered extends Call { - const CancelRecovered({required this.account}); - - factory CancelRecovered._decode(_i1.Input input) { - return CancelRecovered(account: _i3.MultiAddress.codec.decode(input)); - } - - /// AccountIdLookupOf - final _i3.MultiAddress account; - - @override - Map>> toJson() => { - 'cancel_recovered': {'account': account.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.MultiAddress.codec.sizeHint(account); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(8, output); - _i3.MultiAddress.codec.encodeTo(account, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is CancelRecovered && other.account == account; - - @override - int get hashCode => account.hashCode; -} - -/// Poke deposits for recovery configurations and / or active recoveries. -/// -/// This can be used by accounts to possibly lower their locked amount. -/// -/// The dispatch origin for this call must be _Signed_. -/// -/// Parameters: -/// - `maybe_account`: Optional recoverable account for which you have an active recovery -/// and want to adjust the deposit for the active recovery. -/// -/// This function checks both recovery configuration deposit and active recovery deposits -/// of the caller: -/// - If the caller has created a recovery configuration, checks and adjusts its deposit -/// - If the caller has initiated any active recoveries, and provides the account in -/// `maybe_account`, checks and adjusts those deposits -/// -/// If any deposit is updated, the difference will be reserved/unreserved from the caller's -/// account. -/// -/// The transaction is made free if any deposit is updated and paid otherwise. -/// -/// Emits `DepositPoked` if any deposit is updated. -/// Multiple events may be emitted in case both types of deposits are updated. -class PokeDeposit extends Call { - const PokeDeposit({this.maybeAccount}); - - factory PokeDeposit._decode(_i1.Input input) { - return PokeDeposit(maybeAccount: const _i1.OptionCodec<_i3.MultiAddress>(_i3.MultiAddress.codec).decode(input)); - } - - /// Option> - final _i3.MultiAddress? maybeAccount; - - @override - Map?>> toJson() => { - 'poke_deposit': {'maybeAccount': maybeAccount?.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i1.OptionCodec<_i3.MultiAddress>(_i3.MultiAddress.codec).sizeHint(maybeAccount); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(9, output); - const _i1.OptionCodec<_i3.MultiAddress>(_i3.MultiAddress.codec).encodeTo(maybeAccount, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is PokeDeposit && other.maybeAccount == maybeAccount; - - @override - int get hashCode => maybeAccount.hashCode; -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/error.dart deleted file mode 100644 index a50fbd401..000000000 --- a/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/error.dart +++ /dev/null @@ -1,128 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:typed_data' as _i2; - -import 'package:polkadart/scale_codec.dart' as _i1; - -/// The `Error` enum of this pallet. -enum Error { - /// User is not allowed to make a call on behalf of this account - notAllowed('NotAllowed', 0), - - /// Call is not allowed for a high-security account - callNotAllowedForHighSecurity('CallNotAllowedForHighSecurity', 1), - - /// Threshold must be greater than zero - zeroThreshold('ZeroThreshold', 2), - - /// Friends list must be greater than zero and threshold - notEnoughFriends('NotEnoughFriends', 3), - - /// Friends list must be less than max friends - maxFriends('MaxFriends', 4), - - /// Friends list must be sorted and free of duplicates - notSorted('NotSorted', 5), - - /// This account is not set up for recovery - notRecoverable('NotRecoverable', 6), - - /// This account is already set up for recovery - alreadyRecoverable('AlreadyRecoverable', 7), - - /// A recovery process has already started for this account - alreadyStarted('AlreadyStarted', 8), - - /// A recovery process has not started for this rescuer - notStarted('NotStarted', 9), - - /// This account is not a friend who can vouch - notFriend('NotFriend', 10), - - /// The friend must wait until the delay period to vouch for this recovery - delayPeriod('DelayPeriod', 11), - - /// This user has already vouched for this recovery - alreadyVouched('AlreadyVouched', 12), - - /// The threshold for recovering this account has not been met - threshold('Threshold', 13), - - /// There are still active recovery attempts that need to be closed - stillActive('StillActive', 14), - - /// This account is already set up for recovery - alreadyProxy('AlreadyProxy', 15), - - /// Some internal state is broken. - badState('BadState', 16); - - const Error(this.variantName, this.codecIndex); - - factory Error.decode(_i1.Input input) { - return codec.decode(input); - } - - final String variantName; - - final int codecIndex; - - static const $ErrorCodec codec = $ErrorCodec(); - - String toJson() => variantName; - - _i2.Uint8List encode() { - return codec.encode(this); - } -} - -class $ErrorCodec with _i1.Codec { - const $ErrorCodec(); - - @override - Error decode(_i1.Input input) { - final index = _i1.U8Codec.codec.decode(input); - switch (index) { - case 0: - return Error.notAllowed; - case 1: - return Error.callNotAllowedForHighSecurity; - case 2: - return Error.zeroThreshold; - case 3: - return Error.notEnoughFriends; - case 4: - return Error.maxFriends; - case 5: - return Error.notSorted; - case 6: - return Error.notRecoverable; - case 7: - return Error.alreadyRecoverable; - case 8: - return Error.alreadyStarted; - case 9: - return Error.notStarted; - case 10: - return Error.notFriend; - case 11: - return Error.delayPeriod; - case 12: - return Error.alreadyVouched; - case 13: - return Error.threshold; - case 14: - return Error.stillActive; - case 15: - return Error.alreadyProxy; - case 16: - return Error.badState; - default: - throw Exception('Error: Invalid variant index: "$index"'); - } - } - - @override - void encodeTo(Error value, _i1.Output output) { - _i1.U8Codec.codec.encodeTo(value.codecIndex, output); - } -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/event.dart b/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/event.dart deleted file mode 100644 index 6544b0b11..000000000 --- a/quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/event.dart +++ /dev/null @@ -1,477 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:typed_data' as _i2; - -import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i5; - -import '../../sp_core/crypto/account_id32.dart' as _i3; -import '../deposit_kind.dart' as _i4; - -/// Events type. -abstract class Event { - const Event(); - - factory Event.decode(_i1.Input input) { - return codec.decode(input); - } - - static const $EventCodec codec = $EventCodec(); - - static const $Event values = $Event(); - - _i2.Uint8List encode() { - final output = _i1.ByteOutput(codec.sizeHint(this)); - codec.encodeTo(this, output); - return output.toBytes(); - } - - int sizeHint() { - return codec.sizeHint(this); - } - - Map> toJson(); -} - -class $Event { - const $Event(); - - RecoveryCreated recoveryCreated({required _i3.AccountId32 account}) { - return RecoveryCreated(account: account); - } - - RecoveryInitiated recoveryInitiated({required _i3.AccountId32 lostAccount, required _i3.AccountId32 rescuerAccount}) { - return RecoveryInitiated(lostAccount: lostAccount, rescuerAccount: rescuerAccount); - } - - RecoveryVouched recoveryVouched({ - required _i3.AccountId32 lostAccount, - required _i3.AccountId32 rescuerAccount, - required _i3.AccountId32 sender, - }) { - return RecoveryVouched(lostAccount: lostAccount, rescuerAccount: rescuerAccount, sender: sender); - } - - RecoveryClosed recoveryClosed({required _i3.AccountId32 lostAccount, required _i3.AccountId32 rescuerAccount}) { - return RecoveryClosed(lostAccount: lostAccount, rescuerAccount: rescuerAccount); - } - - AccountRecovered accountRecovered({required _i3.AccountId32 lostAccount, required _i3.AccountId32 rescuerAccount}) { - return AccountRecovered(lostAccount: lostAccount, rescuerAccount: rescuerAccount); - } - - RecoveryRemoved recoveryRemoved({required _i3.AccountId32 lostAccount}) { - return RecoveryRemoved(lostAccount: lostAccount); - } - - DepositPoked depositPoked({ - required _i3.AccountId32 who, - required _i4.DepositKind kind, - required BigInt oldDeposit, - required BigInt newDeposit, - }) { - return DepositPoked(who: who, kind: kind, oldDeposit: oldDeposit, newDeposit: newDeposit); - } -} - -class $EventCodec with _i1.Codec { - const $EventCodec(); - - @override - Event decode(_i1.Input input) { - final index = _i1.U8Codec.codec.decode(input); - switch (index) { - case 0: - return RecoveryCreated._decode(input); - case 1: - return RecoveryInitiated._decode(input); - case 2: - return RecoveryVouched._decode(input); - case 3: - return RecoveryClosed._decode(input); - case 4: - return AccountRecovered._decode(input); - case 5: - return RecoveryRemoved._decode(input); - case 6: - return DepositPoked._decode(input); - default: - throw Exception('Event: Invalid variant index: "$index"'); - } - } - - @override - void encodeTo(Event value, _i1.Output output) { - switch (value.runtimeType) { - case RecoveryCreated: - (value as RecoveryCreated).encodeTo(output); - break; - case RecoveryInitiated: - (value as RecoveryInitiated).encodeTo(output); - break; - case RecoveryVouched: - (value as RecoveryVouched).encodeTo(output); - break; - case RecoveryClosed: - (value as RecoveryClosed).encodeTo(output); - break; - case AccountRecovered: - (value as AccountRecovered).encodeTo(output); - break; - case RecoveryRemoved: - (value as RecoveryRemoved).encodeTo(output); - break; - case DepositPoked: - (value as DepositPoked).encodeTo(output); - break; - default: - throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); - } - } - - @override - int sizeHint(Event value) { - switch (value.runtimeType) { - case RecoveryCreated: - return (value as RecoveryCreated)._sizeHint(); - case RecoveryInitiated: - return (value as RecoveryInitiated)._sizeHint(); - case RecoveryVouched: - return (value as RecoveryVouched)._sizeHint(); - case RecoveryClosed: - return (value as RecoveryClosed)._sizeHint(); - case AccountRecovered: - return (value as AccountRecovered)._sizeHint(); - case RecoveryRemoved: - return (value as RecoveryRemoved)._sizeHint(); - case DepositPoked: - return (value as DepositPoked)._sizeHint(); - default: - throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); - } - } -} - -/// A recovery process has been set up for an account. -class RecoveryCreated extends Event { - const RecoveryCreated({required this.account}); - - factory RecoveryCreated._decode(_i1.Input input) { - return RecoveryCreated(account: const _i1.U8ArrayCodec(32).decode(input)); - } - - /// T::AccountId - final _i3.AccountId32 account; - - @override - Map>> toJson() => { - 'RecoveryCreated': {'account': account.toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(account); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(0, output); - const _i1.U8ArrayCodec(32).encodeTo(account, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is RecoveryCreated && _i5.listsEqual(other.account, account); - - @override - int get hashCode => account.hashCode; -} - -/// A recovery process has been initiated for lost account by rescuer account. -class RecoveryInitiated extends Event { - const RecoveryInitiated({required this.lostAccount, required this.rescuerAccount}); - - factory RecoveryInitiated._decode(_i1.Input input) { - return RecoveryInitiated( - lostAccount: const _i1.U8ArrayCodec(32).decode(input), - rescuerAccount: const _i1.U8ArrayCodec(32).decode(input), - ); - } - - /// T::AccountId - final _i3.AccountId32 lostAccount; - - /// T::AccountId - final _i3.AccountId32 rescuerAccount; - - @override - Map>> toJson() => { - 'RecoveryInitiated': {'lostAccount': lostAccount.toList(), 'rescuerAccount': rescuerAccount.toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(lostAccount); - size = size + const _i3.AccountId32Codec().sizeHint(rescuerAccount); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(1, output); - const _i1.U8ArrayCodec(32).encodeTo(lostAccount, output); - const _i1.U8ArrayCodec(32).encodeTo(rescuerAccount, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is RecoveryInitiated && - _i5.listsEqual(other.lostAccount, lostAccount) && - _i5.listsEqual(other.rescuerAccount, rescuerAccount); - - @override - int get hashCode => Object.hash(lostAccount, rescuerAccount); -} - -/// A recovery process for lost account by rescuer account has been vouched for by sender. -class RecoveryVouched extends Event { - const RecoveryVouched({required this.lostAccount, required this.rescuerAccount, required this.sender}); - - factory RecoveryVouched._decode(_i1.Input input) { - return RecoveryVouched( - lostAccount: const _i1.U8ArrayCodec(32).decode(input), - rescuerAccount: const _i1.U8ArrayCodec(32).decode(input), - sender: const _i1.U8ArrayCodec(32).decode(input), - ); - } - - /// T::AccountId - final _i3.AccountId32 lostAccount; - - /// T::AccountId - final _i3.AccountId32 rescuerAccount; - - /// T::AccountId - final _i3.AccountId32 sender; - - @override - Map>> toJson() => { - 'RecoveryVouched': { - 'lostAccount': lostAccount.toList(), - 'rescuerAccount': rescuerAccount.toList(), - 'sender': sender.toList(), - }, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(lostAccount); - size = size + const _i3.AccountId32Codec().sizeHint(rescuerAccount); - size = size + const _i3.AccountId32Codec().sizeHint(sender); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(2, output); - const _i1.U8ArrayCodec(32).encodeTo(lostAccount, output); - const _i1.U8ArrayCodec(32).encodeTo(rescuerAccount, output); - const _i1.U8ArrayCodec(32).encodeTo(sender, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is RecoveryVouched && - _i5.listsEqual(other.lostAccount, lostAccount) && - _i5.listsEqual(other.rescuerAccount, rescuerAccount) && - _i5.listsEqual(other.sender, sender); - - @override - int get hashCode => Object.hash(lostAccount, rescuerAccount, sender); -} - -/// A recovery process for lost account by rescuer account has been closed. -class RecoveryClosed extends Event { - const RecoveryClosed({required this.lostAccount, required this.rescuerAccount}); - - factory RecoveryClosed._decode(_i1.Input input) { - return RecoveryClosed( - lostAccount: const _i1.U8ArrayCodec(32).decode(input), - rescuerAccount: const _i1.U8ArrayCodec(32).decode(input), - ); - } - - /// T::AccountId - final _i3.AccountId32 lostAccount; - - /// T::AccountId - final _i3.AccountId32 rescuerAccount; - - @override - Map>> toJson() => { - 'RecoveryClosed': {'lostAccount': lostAccount.toList(), 'rescuerAccount': rescuerAccount.toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(lostAccount); - size = size + const _i3.AccountId32Codec().sizeHint(rescuerAccount); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(3, output); - const _i1.U8ArrayCodec(32).encodeTo(lostAccount, output); - const _i1.U8ArrayCodec(32).encodeTo(rescuerAccount, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is RecoveryClosed && - _i5.listsEqual(other.lostAccount, lostAccount) && - _i5.listsEqual(other.rescuerAccount, rescuerAccount); - - @override - int get hashCode => Object.hash(lostAccount, rescuerAccount); -} - -/// Lost account has been successfully recovered by rescuer account. -class AccountRecovered extends Event { - const AccountRecovered({required this.lostAccount, required this.rescuerAccount}); - - factory AccountRecovered._decode(_i1.Input input) { - return AccountRecovered( - lostAccount: const _i1.U8ArrayCodec(32).decode(input), - rescuerAccount: const _i1.U8ArrayCodec(32).decode(input), - ); - } - - /// T::AccountId - final _i3.AccountId32 lostAccount; - - /// T::AccountId - final _i3.AccountId32 rescuerAccount; - - @override - Map>> toJson() => { - 'AccountRecovered': {'lostAccount': lostAccount.toList(), 'rescuerAccount': rescuerAccount.toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(lostAccount); - size = size + const _i3.AccountId32Codec().sizeHint(rescuerAccount); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(4, output); - const _i1.U8ArrayCodec(32).encodeTo(lostAccount, output); - const _i1.U8ArrayCodec(32).encodeTo(rescuerAccount, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is AccountRecovered && - _i5.listsEqual(other.lostAccount, lostAccount) && - _i5.listsEqual(other.rescuerAccount, rescuerAccount); - - @override - int get hashCode => Object.hash(lostAccount, rescuerAccount); -} - -/// A recovery process has been removed for an account. -class RecoveryRemoved extends Event { - const RecoveryRemoved({required this.lostAccount}); - - factory RecoveryRemoved._decode(_i1.Input input) { - return RecoveryRemoved(lostAccount: const _i1.U8ArrayCodec(32).decode(input)); - } - - /// T::AccountId - final _i3.AccountId32 lostAccount; - - @override - Map>> toJson() => { - 'RecoveryRemoved': {'lostAccount': lostAccount.toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(lostAccount); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(5, output); - const _i1.U8ArrayCodec(32).encodeTo(lostAccount, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is RecoveryRemoved && _i5.listsEqual(other.lostAccount, lostAccount); - - @override - int get hashCode => lostAccount.hashCode; -} - -/// A deposit has been updated. -class DepositPoked extends Event { - const DepositPoked({required this.who, required this.kind, required this.oldDeposit, required this.newDeposit}); - - factory DepositPoked._decode(_i1.Input input) { - return DepositPoked( - who: const _i1.U8ArrayCodec(32).decode(input), - kind: _i4.DepositKind.codec.decode(input), - oldDeposit: _i1.U128Codec.codec.decode(input), - newDeposit: _i1.U128Codec.codec.decode(input), - ); - } - - /// T::AccountId - final _i3.AccountId32 who; - - /// DepositKind - final _i4.DepositKind kind; - - /// BalanceOf - final BigInt oldDeposit; - - /// BalanceOf - final BigInt newDeposit; - - @override - Map> toJson() => { - 'DepositPoked': {'who': who.toList(), 'kind': kind.toJson(), 'oldDeposit': oldDeposit, 'newDeposit': newDeposit}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i3.AccountId32Codec().sizeHint(who); - size = size + _i4.DepositKind.codec.sizeHint(kind); - size = size + _i1.U128Codec.codec.sizeHint(oldDeposit); - size = size + _i1.U128Codec.codec.sizeHint(newDeposit); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(6, output); - const _i1.U8ArrayCodec(32).encodeTo(who, output); - _i4.DepositKind.codec.encodeTo(kind, output); - _i1.U128Codec.codec.encodeTo(oldDeposit, output); - _i1.U128Codec.codec.encodeTo(newDeposit, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || - other is DepositPoked && - _i5.listsEqual(other.who, who) && - other.kind == kind && - other.oldDeposit == oldDeposit && - other.newDeposit == newDeposit; - - @override - int get hashCode => Object.hash(who, kind, oldDeposit, newDeposit); -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_recovery/recovery_config.dart b/quantus_sdk/lib/generated/planck/types/pallet_recovery/recovery_config.dart deleted file mode 100644 index 2a6992a2f..000000000 --- a/quantus_sdk/lib/generated/planck/types/pallet_recovery/recovery_config.dart +++ /dev/null @@ -1,89 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:typed_data' as _i3; - -import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i4; - -import '../sp_core/crypto/account_id32.dart' as _i2; - -class RecoveryConfig { - const RecoveryConfig({ - required this.delayPeriod, - required this.deposit, - required this.friends, - required this.threshold, - }); - - factory RecoveryConfig.decode(_i1.Input input) { - return codec.decode(input); - } - - /// BlockNumber - final int delayPeriod; - - /// Balance - final BigInt deposit; - - /// Friends - final List<_i2.AccountId32> friends; - - /// u16 - final int threshold; - - static const $RecoveryConfigCodec codec = $RecoveryConfigCodec(); - - _i3.Uint8List encode() { - return codec.encode(this); - } - - Map toJson() => { - 'delayPeriod': delayPeriod, - 'deposit': deposit, - 'friends': friends.map((value) => value.toList()).toList(), - 'threshold': threshold, - }; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is RecoveryConfig && - other.delayPeriod == delayPeriod && - other.deposit == deposit && - _i4.listsEqual(other.friends, friends) && - other.threshold == threshold; - - @override - int get hashCode => Object.hash(delayPeriod, deposit, friends, threshold); -} - -class $RecoveryConfigCodec with _i1.Codec { - const $RecoveryConfigCodec(); - - @override - void encodeTo(RecoveryConfig obj, _i1.Output output) { - _i1.U32Codec.codec.encodeTo(obj.delayPeriod, output); - _i1.U128Codec.codec.encodeTo(obj.deposit, output); - const _i1.SequenceCodec<_i2.AccountId32>(_i2.AccountId32Codec()).encodeTo(obj.friends, output); - _i1.U16Codec.codec.encodeTo(obj.threshold, output); - } - - @override - RecoveryConfig decode(_i1.Input input) { - return RecoveryConfig( - delayPeriod: _i1.U32Codec.codec.decode(input), - deposit: _i1.U128Codec.codec.decode(input), - friends: const _i1.SequenceCodec<_i2.AccountId32>(_i2.AccountId32Codec()).decode(input), - threshold: _i1.U16Codec.codec.decode(input), - ); - } - - @override - int sizeHint(RecoveryConfig obj) { - int size = 0; - size = size + _i1.U32Codec.codec.sizeHint(obj.delayPeriod); - size = size + _i1.U128Codec.codec.sizeHint(obj.deposit); - size = size + const _i1.SequenceCodec<_i2.AccountId32>(_i2.AccountId32Codec()).sizeHint(obj.friends); - size = size + _i1.U16Codec.codec.sizeHint(obj.threshold); - return size; - } -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/call.dart b/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/call.dart index ad01d94d3..08022436b 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/call.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/call.dart @@ -172,6 +172,21 @@ class $CallCodec with _i1.Codec { /// - `delay`: The reversibility time for any transfer made by the high-security account. /// - `guardian`: The guardian account that can cancel pending transfers and recover funds /// from this high-security account. +/// +/// # Choose the guardian carefully +/// +/// The guardian holds instant, total seizure power: `recover_funds` +/// sweeps every hold plus the entire free balance to the guardian, +/// with no delay, no second approver, and no way to change the +/// relationship afterwards. A single-key guardian is therefore a +/// single point of failure for the whole scheme. **Use a multisig +/// address as the guardian**: `pallet_multisig` dispatches calls as +/// its derived address, so a multisig can cancel and recover exactly +/// like a plain account. +/// +/// Guardianship is discoverable offchain (e.g. Subsquid) via the +/// `HighSecuritySet` event; there is deliberately no on-chain +/// guardian index to fill up or grief. class SetHighSecurity extends Call { const SetHighSecurity({required this.delay, required this.guardian}); @@ -262,6 +277,15 @@ class Cancel extends Call { /// /// - `tx_id`: The unique identifier of the pending transfer to execute. /// +/// Execution uses `transfer_allow_death` so a sender who spent their leftover +/// free balance during the delay still completes. A failed inner transfer (e.g. +/// dest overflow, or `amount < ED` to a new account) does not fail this +/// extrinsic: the hold is already released and the pending transfer is already +/// removed. Propagating that error would roll back those writes (FRAME +/// dispatchables are transactional) while Scheduler terminally drops the named +/// task, freezing the funds with no retry. The inner result is still recorded on +/// [`Event::TransactionExecuted`]. +/// /// # Errors /// /// - [`InvalidSchedulerOrigin`](Error::InvalidSchedulerOrigin): Called by an account other diff --git a/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/error.dart index a5ea4274a..b41af90b7 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/error.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_reversible_transfers/pallet/error.dart @@ -45,15 +45,12 @@ enum Error { /// deterrence) accountAlreadyReversibleCannotScheduleOneTime('AccountAlreadyReversibleCannotScheduleOneTime', 12), - /// The guardian has reached the maximum number of accounts they can protect. - tooManyGuardianAccounts('TooManyGuardianAccounts', 13), - /// Asset transfers are not supported. - assetsNotSupported('AssetsNotSupported', 14), + assetsNotSupported('AssetsNotSupported', 13), /// Zero-amount transfers cannot be scheduled: there is nothing to hold, /// execute, or reverse. - zeroAmount('ZeroAmount', 15); + zeroAmount('ZeroAmount', 14); const Error(this.variantName, this.codecIndex); @@ -108,10 +105,8 @@ class $ErrorCodec with _i1.Codec { case 12: return Error.accountAlreadyReversibleCannotScheduleOneTime; case 13: - return Error.tooManyGuardianAccounts; - case 14: return Error.assetsNotSupported; - case 15: + case 14: return Error.zeroAmount; default: throw Exception('Error: Invalid variant index: "$index"'); diff --git a/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/call.dart b/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/call.dart index 12fcd0086..c1cc3e7d3 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/call.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/call.dart @@ -2,9 +2,8 @@ import 'dart:typed_data' as _i2; import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i5; +import 'package:quiver/collection.dart' as _i4; -import '../../sp_arithmetic/per_things/permill.dart' as _i4; import '../../sp_core/crypto/account_id32.dart' as _i3; /// Contains a variant per dispatchable extrinsic that this pallet has. @@ -29,7 +28,7 @@ abstract class Call { return codec.sizeHint(this); } - Map> toJson(); + Map>> toJson(); } class $Call { @@ -38,10 +37,6 @@ class $Call { SetTreasuryAccount setTreasuryAccount({required _i3.AccountId32 account}) { return SetTreasuryAccount(account: account); } - - SetTreasuryPortion setTreasuryPortion({required _i4.Permill portion}) { - return SetTreasuryPortion(portion: portion); - } } class $CallCodec with _i1.Codec { @@ -53,8 +48,6 @@ class $CallCodec with _i1.Codec { switch (index) { case 0: return SetTreasuryAccount._decode(input); - case 1: - return SetTreasuryPortion._decode(input); default: throw Exception('Call: Invalid variant index: "$index"'); } @@ -66,9 +59,6 @@ class $CallCodec with _i1.Codec { case SetTreasuryAccount: (value as SetTreasuryAccount).encodeTo(output); break; - case SetTreasuryPortion: - (value as SetTreasuryPortion).encodeTo(output); - break; default: throw Exception('Call: Unsupported "$value" of type "${value.runtimeType}"'); } @@ -79,8 +69,6 @@ class $CallCodec with _i1.Codec { switch (value.runtimeType) { case SetTreasuryAccount: return (value as SetTreasuryAccount)._sizeHint(); - case SetTreasuryPortion: - return (value as SetTreasuryPortion)._sizeHint(); default: throw Exception('Call: Unsupported "$value" of type "${value.runtimeType}"'); } @@ -89,7 +77,7 @@ class $CallCodec with _i1.Codec { /// Set the treasury account. Root only. Zero address is rejected (funds would be locked). /// -/// **Important**: This only changes where *future* mining rewards are sent. Any balance +/// **Important**: This only changes where *future* treasury credits are sent. Any balance /// that has already accumulated in the current treasury account is NOT automatically /// migrated to the new account. If you need to move existing funds, perform a separate /// balance transfer (e.g., via governance proposal) after updating the account. @@ -121,42 +109,8 @@ class SetTreasuryAccount extends Call { @override bool operator ==(Object other) => - identical(this, other) || other is SetTreasuryAccount && _i5.listsEqual(other.account, account); + identical(this, other) || other is SetTreasuryAccount && _i4.listsEqual(other.account, account); @override int get hashCode => account.hashCode; } - -/// Set the treasury portion (Permill, 0–100%). Root only. -class SetTreasuryPortion extends Call { - const SetTreasuryPortion({required this.portion}); - - factory SetTreasuryPortion._decode(_i1.Input input) { - return SetTreasuryPortion(portion: _i1.U32Codec.codec.decode(input)); - } - - /// Permill - final _i4.Permill portion; - - @override - Map> toJson() => { - 'set_treasury_portion': {'portion': portion}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i4.PermillCodec().sizeHint(portion); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(1, output); - _i1.U32Codec.codec.encodeTo(portion, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is SetTreasuryPortion && other.portion == portion; - - @override - int get hashCode => portion.hashCode; -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/error.dart index 51d124154..d684be739 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/error.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/error.dart @@ -5,10 +5,8 @@ import 'package:polkadart/scale_codec.dart' as _i1; /// The `Error` enum of this pallet. enum Error { - invalidPortion('InvalidPortion', 0), - /// Treasury account cannot be zero address (funds would be permanently locked). - invalidTreasuryAccount('InvalidTreasuryAccount', 1); + invalidTreasuryAccount('InvalidTreasuryAccount', 0); const Error(this.variantName, this.codecIndex); @@ -37,8 +35,6 @@ class $ErrorCodec with _i1.Codec { final index = _i1.U8Codec.codec.decode(input); switch (index) { case 0: - return Error.invalidPortion; - case 1: return Error.invalidTreasuryAccount; default: throw Exception('Error: Invalid variant index: "$index"'); diff --git a/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/event.dart b/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/event.dart index 42854775d..63bd5333d 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/event.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_treasury/pallet/event.dart @@ -2,9 +2,8 @@ import 'dart:typed_data' as _i2; import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i5; +import 'package:quiver/collection.dart' as _i4; -import '../../sp_arithmetic/per_things/permill.dart' as _i4; import '../../sp_core/crypto/account_id32.dart' as _i3; /// The `Event` enum of this pallet @@ -29,7 +28,7 @@ abstract class Event { return codec.sizeHint(this); } - Map> toJson(); + Map?>> toJson(); } class $Event { @@ -38,10 +37,6 @@ class $Event { TreasuryAccountUpdated treasuryAccountUpdated({_i3.AccountId32? oldAccount, required _i3.AccountId32 newAccount}) { return TreasuryAccountUpdated(oldAccount: oldAccount, newAccount: newAccount); } - - TreasuryPortionUpdated treasuryPortionUpdated({required _i4.Permill newPortion}) { - return TreasuryPortionUpdated(newPortion: newPortion); - } } class $EventCodec with _i1.Codec { @@ -53,8 +48,6 @@ class $EventCodec with _i1.Codec { switch (index) { case 0: return TreasuryAccountUpdated._decode(input); - case 1: - return TreasuryPortionUpdated._decode(input); default: throw Exception('Event: Invalid variant index: "$index"'); } @@ -66,9 +59,6 @@ class $EventCodec with _i1.Codec { case TreasuryAccountUpdated: (value as TreasuryAccountUpdated).encodeTo(output); break; - case TreasuryPortionUpdated: - (value as TreasuryPortionUpdated).encodeTo(output); - break; default: throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); } @@ -79,8 +69,6 @@ class $EventCodec with _i1.Codec { switch (value.runtimeType) { case TreasuryAccountUpdated: return (value as TreasuryAccountUpdated)._sizeHint(); - case TreasuryPortionUpdated: - return (value as TreasuryPortionUpdated)._sizeHint(); default: throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); } @@ -89,7 +77,7 @@ class $EventCodec with _i1.Codec { /// The treasury account was updated. /// -/// Note: This only redirects where future mining rewards are sent. Any balance +/// Note: This only redirects where future treasury credits are sent. Any balance /// accumulated in the old account remains there and is NOT automatically migrated. /// Use a separate balance transfer if funds need to be moved. class TreasuryAccountUpdated extends Event { @@ -107,7 +95,7 @@ class TreasuryAccountUpdated extends Event { final _i3.AccountId32? oldAccount; /// T::AccountId - /// The new treasury account that will receive future rewards. + /// The new treasury account that will receive future credits. final _i3.AccountId32 newAccount; @override @@ -131,43 +119,8 @@ class TreasuryAccountUpdated extends Event { @override bool operator ==(Object other) => identical(this, other) || - other is TreasuryAccountUpdated && other.oldAccount == oldAccount && _i5.listsEqual(other.newAccount, newAccount); + other is TreasuryAccountUpdated && other.oldAccount == oldAccount && _i4.listsEqual(other.newAccount, newAccount); @override int get hashCode => Object.hash(oldAccount, newAccount); } - -/// The treasury portion (share of mining rewards) was updated. -class TreasuryPortionUpdated extends Event { - const TreasuryPortionUpdated({required this.newPortion}); - - factory TreasuryPortionUpdated._decode(_i1.Input input) { - return TreasuryPortionUpdated(newPortion: _i1.U32Codec.codec.decode(input)); - } - - /// Permill - final _i4.Permill newPortion; - - @override - Map> toJson() => { - 'TreasuryPortionUpdated': {'newPortion': newPortion}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i4.PermillCodec().sizeHint(newPortion); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(1, output); - _i1.U32Codec.codec.encodeTo(newPortion, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is TreasuryPortionUpdated && other.newPortion == newPortion; - - @override - int get hashCode => newPortion.hashCode; -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/call.dart b/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/call.dart index 3788829af..82b250be2 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/call.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/call.dart @@ -2,11 +2,9 @@ import 'dart:typed_data' as _i2; import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i6; +import 'package:quiver/collection.dart' as _i4; -import '../../quantus_runtime/origin_caller.dart' as _i4; import '../../quantus_runtime/runtime_call.dart' as _i3; -import '../../sp_weights/weight_v2/weight.dart' as _i5; /// Contains a variant per dispatchable extrinsic that this pallet has. abstract class Call { @@ -30,43 +28,15 @@ abstract class Call { return codec.sizeHint(this); } - Map> toJson(); + Map>>>> toJson(); } class $Call { const $Call(); - Batch batch({required List<_i3.RuntimeCall> calls}) { - return Batch(calls: calls); - } - - AsDerivative asDerivative({required int index, required _i3.RuntimeCall call}) { - return AsDerivative(index: index, call: call); - } - BatchAll batchAll({required List<_i3.RuntimeCall> calls}) { return BatchAll(calls: calls); } - - DispatchAs dispatchAs({required _i4.OriginCaller asOrigin, required _i3.RuntimeCall call}) { - return DispatchAs(asOrigin: asOrigin, call: call); - } - - ForceBatch forceBatch({required List<_i3.RuntimeCall> calls}) { - return ForceBatch(calls: calls); - } - - WithWeight withWeight({required _i3.RuntimeCall call, required _i5.Weight weight}) { - return WithWeight(call: call, weight: weight); - } - - IfElse ifElse({required _i3.RuntimeCall main, required _i3.RuntimeCall fallback}) { - return IfElse(main: main, fallback: fallback); - } - - DispatchAsFallible dispatchAsFallible({required _i4.OriginCaller asOrigin, required _i3.RuntimeCall call}) { - return DispatchAsFallible(asOrigin: asOrigin, call: call); - } } class $CallCodec with _i1.Codec { @@ -76,22 +46,8 @@ class $CallCodec with _i1.Codec { Call decode(_i1.Input input) { final index = _i1.U8Codec.codec.decode(input); switch (index) { - case 0: - return Batch._decode(input); - case 1: - return AsDerivative._decode(input); case 2: return BatchAll._decode(input); - case 3: - return DispatchAs._decode(input); - case 4: - return ForceBatch._decode(input); - case 5: - return WithWeight._decode(input); - case 6: - return IfElse._decode(input); - case 7: - return DispatchAsFallible._decode(input); default: throw Exception('Call: Invalid variant index: "$index"'); } @@ -100,30 +56,9 @@ class $CallCodec with _i1.Codec { @override void encodeTo(Call value, _i1.Output output) { switch (value.runtimeType) { - case Batch: - (value as Batch).encodeTo(output); - break; - case AsDerivative: - (value as AsDerivative).encodeTo(output); - break; case BatchAll: (value as BatchAll).encodeTo(output); break; - case DispatchAs: - (value as DispatchAs).encodeTo(output); - break; - case ForceBatch: - (value as ForceBatch).encodeTo(output); - break; - case WithWeight: - (value as WithWeight).encodeTo(output); - break; - case IfElse: - (value as IfElse).encodeTo(output); - break; - case DispatchAsFallible: - (value as DispatchAsFallible).encodeTo(output); - break; default: throw Exception('Call: Unsupported "$value" of type "${value.runtimeType}"'); } @@ -132,131 +67,14 @@ class $CallCodec with _i1.Codec { @override int sizeHint(Call value) { switch (value.runtimeType) { - case Batch: - return (value as Batch)._sizeHint(); - case AsDerivative: - return (value as AsDerivative)._sizeHint(); case BatchAll: return (value as BatchAll)._sizeHint(); - case DispatchAs: - return (value as DispatchAs)._sizeHint(); - case ForceBatch: - return (value as ForceBatch)._sizeHint(); - case WithWeight: - return (value as WithWeight)._sizeHint(); - case IfElse: - return (value as IfElse)._sizeHint(); - case DispatchAsFallible: - return (value as DispatchAsFallible)._sizeHint(); default: throw Exception('Call: Unsupported "$value" of type "${value.runtimeType}"'); } } } -/// Send a batch of dispatch calls. -/// -/// May be called from any origin except `None`. -/// -/// - `calls`: The calls to be dispatched from the same origin. The number of call must not -/// exceed the constant: `batched_calls_limit` (available in constant metadata). -/// -/// If origin is root then the calls are dispatched without checking origin filter. (This -/// includes bypassing `frame_system::Config::BaseCallFilter`). -/// -/// ## Complexity -/// - O(C) where C is the number of calls to be batched. -/// -/// This will return `Ok` in all circumstances. To determine the success of the batch, an -/// event is deposited. If a call failed and the batch was interrupted, then the -/// `BatchInterrupted` event is deposited, along with the number of successful calls made -/// and the error of the failed call. If all were successful, then the `BatchCompleted` -/// event is deposited. -class Batch extends Call { - const Batch({required this.calls}); - - factory Batch._decode(_i1.Input input) { - return Batch(calls: const _i1.SequenceCodec<_i3.RuntimeCall>(_i3.RuntimeCall.codec).decode(input)); - } - - /// Vec<::RuntimeCall> - final List<_i3.RuntimeCall> calls; - - @override - Map>>>> toJson() => { - 'batch': {'calls': calls.map((value) => value.toJson()).toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i1.SequenceCodec<_i3.RuntimeCall>(_i3.RuntimeCall.codec).sizeHint(calls); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(0, output); - const _i1.SequenceCodec<_i3.RuntimeCall>(_i3.RuntimeCall.codec).encodeTo(calls, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is Batch && _i6.listsEqual(other.calls, calls); - - @override - int get hashCode => calls.hashCode; -} - -/// Send a call through an indexed pseudonym of the sender. -/// -/// Filter from origin are passed along. The call will be dispatched with an origin which -/// use the same filter as the origin of this call. -/// -/// NOTE: If you need to ensure that any account-based filtering is not honored (i.e. -/// because you expect `proxy` to have been used prior in the call stack and you do not want -/// the call restrictions to apply to any sub-accounts), then use `as_multi_threshold_1` -/// in the Multisig pallet instead. -/// -/// NOTE: Prior to version *12, this was called `as_limited_sub`. -/// -/// The dispatch origin for this call must be _Signed_. -class AsDerivative extends Call { - const AsDerivative({required this.index, required this.call}); - - factory AsDerivative._decode(_i1.Input input) { - return AsDerivative(index: _i1.U16Codec.codec.decode(input), call: _i3.RuntimeCall.codec.decode(input)); - } - - /// u16 - final int index; - - /// Box<::RuntimeCall> - final _i3.RuntimeCall call; - - @override - Map> toJson() => { - 'as_derivative': {'index': index, 'call': call.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i1.U16Codec.codec.sizeHint(index); - size = size + _i3.RuntimeCall.codec.sizeHint(call); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(1, output); - _i1.U16Codec.codec.encodeTo(index, output); - _i3.RuntimeCall.codec.encodeTo(call, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is AsDerivative && other.index == index && other.call == call; - - @override - int get hashCode => Object.hash(index, call); -} - /// Send a batch of dispatch calls and atomically execute them. /// The whole transaction will rollback and fail if any of the calls failed. /// @@ -270,6 +88,9 @@ class AsDerivative extends Call { /// /// ## Complexity /// - O(C) where C is the number of calls to be batched. +/// +/// Call index 2 is preserved from the upstream utility pallet so existing +/// `batch_all` encodings keep decoding after the other combinators were removed. class BatchAll extends Call { const BatchAll({required this.calls}); @@ -281,7 +102,7 @@ class BatchAll extends Call { final List<_i3.RuntimeCall> calls; @override - Map>> toJson() => { + Map>>>> toJson() => { 'batch_all': {'calls': calls.map((value) => value.toJson()).toList()}, }; @@ -297,253 +118,8 @@ class BatchAll extends Call { } @override - bool operator ==(Object other) => identical(this, other) || other is BatchAll && _i6.listsEqual(other.calls, calls); - - @override - int get hashCode => calls.hashCode; -} - -/// Dispatches a function call with a provided origin. -/// -/// The dispatch origin for this call must be _Root_. -/// -/// ## Complexity -/// - O(1). -class DispatchAs extends Call { - const DispatchAs({required this.asOrigin, required this.call}); - - factory DispatchAs._decode(_i1.Input input) { - return DispatchAs(asOrigin: _i4.OriginCaller.codec.decode(input), call: _i3.RuntimeCall.codec.decode(input)); - } - - /// Box - final _i4.OriginCaller asOrigin; - - /// Box<::RuntimeCall> - final _i3.RuntimeCall call; - - @override - Map>> toJson() => { - 'dispatch_as': {'asOrigin': asOrigin.toJson(), 'call': call.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i4.OriginCaller.codec.sizeHint(asOrigin); - size = size + _i3.RuntimeCall.codec.sizeHint(call); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(3, output); - _i4.OriginCaller.codec.encodeTo(asOrigin, output); - _i3.RuntimeCall.codec.encodeTo(call, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is DispatchAs && other.asOrigin == asOrigin && other.call == call; - - @override - int get hashCode => Object.hash(asOrigin, call); -} - -/// Send a batch of dispatch calls. -/// Unlike `batch`, it allows errors and won't interrupt. -/// -/// May be called from any origin except `None`. -/// -/// - `calls`: The calls to be dispatched from the same origin. The number of call must not -/// exceed the constant: `batched_calls_limit` (available in constant metadata). -/// -/// If origin is root then the calls are dispatch without checking origin filter. (This -/// includes bypassing `frame_system::Config::BaseCallFilter`). -/// -/// ## Complexity -/// - O(C) where C is the number of calls to be batched. -class ForceBatch extends Call { - const ForceBatch({required this.calls}); - - factory ForceBatch._decode(_i1.Input input) { - return ForceBatch(calls: const _i1.SequenceCodec<_i3.RuntimeCall>(_i3.RuntimeCall.codec).decode(input)); - } - - /// Vec<::RuntimeCall> - final List<_i3.RuntimeCall> calls; - - @override - Map>> toJson() => { - 'force_batch': {'calls': calls.map((value) => value.toJson()).toList()}, - }; - - int _sizeHint() { - int size = 1; - size = size + const _i1.SequenceCodec<_i3.RuntimeCall>(_i3.RuntimeCall.codec).sizeHint(calls); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(4, output); - const _i1.SequenceCodec<_i3.RuntimeCall>(_i3.RuntimeCall.codec).encodeTo(calls, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is ForceBatch && _i6.listsEqual(other.calls, calls); + bool operator ==(Object other) => identical(this, other) || other is BatchAll && _i4.listsEqual(other.calls, calls); @override int get hashCode => calls.hashCode; } - -/// Dispatch a function call with a specified weight. -/// -/// This function does not check the weight of the call, and instead allows the -/// Root origin to specify the weight of the call. -/// -/// The dispatch origin for this call must be _Root_. -class WithWeight extends Call { - const WithWeight({required this.call, required this.weight}); - - factory WithWeight._decode(_i1.Input input) { - return WithWeight(call: _i3.RuntimeCall.codec.decode(input), weight: _i5.Weight.codec.decode(input)); - } - - /// Box<::RuntimeCall> - final _i3.RuntimeCall call; - - /// Weight - final _i5.Weight weight; - - @override - Map>> toJson() => { - 'with_weight': {'call': call.toJson(), 'weight': weight.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.RuntimeCall.codec.sizeHint(call); - size = size + _i5.Weight.codec.sizeHint(weight); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(5, output); - _i3.RuntimeCall.codec.encodeTo(call, output); - _i5.Weight.codec.encodeTo(weight, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is WithWeight && other.call == call && other.weight == weight; - - @override - int get hashCode => Object.hash(call, weight); -} - -/// Dispatch a fallback call in the event the main call fails to execute. -/// May be called from any origin except `None`. -/// -/// This function first attempts to dispatch the `main` call. -/// If the `main` call fails, the `fallback` is attemted. -/// if the fallback is successfully dispatched, the weights of both calls -/// are accumulated and an event containing the main call error is deposited. -/// -/// In the event of a fallback failure the whole call fails -/// with the weights returned. -/// -/// - `main`: The main call to be dispatched. This is the primary action to execute. -/// - `fallback`: The fallback call to be dispatched in case the `main` call fails. -/// -/// ## Dispatch Logic -/// - If the origin is `root`, both the main and fallback calls are executed without -/// applying any origin filters. -/// - If the origin is not `root`, the origin filter is applied to both the `main` and -/// `fallback` calls. -/// -/// ## Use Case -/// - Some use cases might involve submitting a `batch` type call in either main, fallback -/// or both. -class IfElse extends Call { - const IfElse({required this.main, required this.fallback}); - - factory IfElse._decode(_i1.Input input) { - return IfElse(main: _i3.RuntimeCall.codec.decode(input), fallback: _i3.RuntimeCall.codec.decode(input)); - } - - /// Box<::RuntimeCall> - final _i3.RuntimeCall main; - - /// Box<::RuntimeCall> - final _i3.RuntimeCall fallback; - - @override - Map>> toJson() => { - 'if_else': {'main': main.toJson(), 'fallback': fallback.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.RuntimeCall.codec.sizeHint(main); - size = size + _i3.RuntimeCall.codec.sizeHint(fallback); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(6, output); - _i3.RuntimeCall.codec.encodeTo(main, output); - _i3.RuntimeCall.codec.encodeTo(fallback, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is IfElse && other.main == main && other.fallback == fallback; - - @override - int get hashCode => Object.hash(main, fallback); -} - -/// Dispatches a function call with a provided origin. -/// -/// Almost the same as [`Pallet::dispatch_as`] but forwards any error of the inner call. -/// -/// The dispatch origin for this call must be _Root_. -class DispatchAsFallible extends Call { - const DispatchAsFallible({required this.asOrigin, required this.call}); - - factory DispatchAsFallible._decode(_i1.Input input) { - return DispatchAsFallible( - asOrigin: _i4.OriginCaller.codec.decode(input), - call: _i3.RuntimeCall.codec.decode(input), - ); - } - - /// Box - final _i4.OriginCaller asOrigin; - - /// Box<::RuntimeCall> - final _i3.RuntimeCall call; - - @override - Map>> toJson() => { - 'dispatch_as_fallible': {'asOrigin': asOrigin.toJson(), 'call': call.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i4.OriginCaller.codec.sizeHint(asOrigin); - size = size + _i3.RuntimeCall.codec.sizeHint(call); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(7, output); - _i4.OriginCaller.codec.encodeTo(asOrigin, output); - _i3.RuntimeCall.codec.encodeTo(call, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is DispatchAsFallible && other.asOrigin == asOrigin && other.call == call; - - @override - int get hashCode => Object.hash(asOrigin, call); -} diff --git a/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/event.dart b/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/event.dart index 4f8e50956..425a06068 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/event.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_utility/pallet/event.dart @@ -3,66 +3,30 @@ import 'dart:typed_data' as _i2; import 'package:polkadart/scale_codec.dart' as _i1; -import '../../sp_runtime/dispatch_error.dart' as _i3; - /// The `Event` enum of this pallet -abstract class Event { - const Event(); - - factory Event.decode(_i1.Input input) { - return codec.decode(input); - } +enum Event { + /// Batch of dispatches completed fully with no error. + batchCompleted('BatchCompleted', 0), - static const $EventCodec codec = $EventCodec(); - - static const $Event values = $Event(); - - _i2.Uint8List encode() { - final output = _i1.ByteOutput(codec.sizeHint(this)); - codec.encodeTo(this, output); - return output.toBytes(); - } - - int sizeHint() { - return codec.sizeHint(this); - } - - Map toJson(); -} - -class $Event { - const $Event(); - - BatchInterrupted batchInterrupted({required int index, required _i3.DispatchError error}) { - return BatchInterrupted(index: index, error: error); - } + /// A single item within a Batch of dispatches has completed with no error. + itemCompleted('ItemCompleted', 1); - BatchCompleted batchCompleted() { - return BatchCompleted(); - } + const Event(this.variantName, this.codecIndex); - BatchCompletedWithErrors batchCompletedWithErrors() { - return BatchCompletedWithErrors(); + factory Event.decode(_i1.Input input) { + return codec.decode(input); } - ItemCompleted itemCompleted() { - return ItemCompleted(); - } + final String variantName; - ItemFailed itemFailed({required _i3.DispatchError error}) { - return ItemFailed(error: error); - } + final int codecIndex; - DispatchedAs dispatchedAs({required _i1.Result result}) { - return DispatchedAs(result: result); - } + static const $EventCodec codec = $EventCodec(); - IfElseMainSuccess ifElseMainSuccess() { - return IfElseMainSuccess(); - } + String toJson() => variantName; - IfElseFallbackCalled ifElseFallbackCalled({required _i3.DispatchError mainError}) { - return IfElseFallbackCalled(mainError: mainError); + _i2.Uint8List encode() { + return codec.encode(this); } } @@ -74,21 +38,9 @@ class $EventCodec with _i1.Codec { final index = _i1.U8Codec.codec.decode(input); switch (index) { case 0: - return BatchInterrupted._decode(input); + return Event.batchCompleted; case 1: - return const BatchCompleted(); - case 2: - return const BatchCompletedWithErrors(); - case 3: - return const ItemCompleted(); - case 4: - return ItemFailed._decode(input); - case 5: - return DispatchedAs._decode(input); - case 6: - return const IfElseMainSuccess(); - case 7: - return IfElseFallbackCalled._decode(input); + return Event.itemCompleted; default: throw Exception('Event: Invalid variant index: "$index"'); } @@ -96,286 +48,6 @@ class $EventCodec with _i1.Codec { @override void encodeTo(Event value, _i1.Output output) { - switch (value.runtimeType) { - case BatchInterrupted: - (value as BatchInterrupted).encodeTo(output); - break; - case BatchCompleted: - (value as BatchCompleted).encodeTo(output); - break; - case BatchCompletedWithErrors: - (value as BatchCompletedWithErrors).encodeTo(output); - break; - case ItemCompleted: - (value as ItemCompleted).encodeTo(output); - break; - case ItemFailed: - (value as ItemFailed).encodeTo(output); - break; - case DispatchedAs: - (value as DispatchedAs).encodeTo(output); - break; - case IfElseMainSuccess: - (value as IfElseMainSuccess).encodeTo(output); - break; - case IfElseFallbackCalled: - (value as IfElseFallbackCalled).encodeTo(output); - break; - default: - throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); - } - } - - @override - int sizeHint(Event value) { - switch (value.runtimeType) { - case BatchInterrupted: - return (value as BatchInterrupted)._sizeHint(); - case BatchCompleted: - return 1; - case BatchCompletedWithErrors: - return 1; - case ItemCompleted: - return 1; - case ItemFailed: - return (value as ItemFailed)._sizeHint(); - case DispatchedAs: - return (value as DispatchedAs)._sizeHint(); - case IfElseMainSuccess: - return 1; - case IfElseFallbackCalled: - return (value as IfElseFallbackCalled)._sizeHint(); - default: - throw Exception('Event: Unsupported "$value" of type "${value.runtimeType}"'); - } - } -} - -/// Batch of dispatches did not complete fully. Index of first failing dispatch given, as -/// well as the error. -class BatchInterrupted extends Event { - const BatchInterrupted({required this.index, required this.error}); - - factory BatchInterrupted._decode(_i1.Input input) { - return BatchInterrupted(index: _i1.U32Codec.codec.decode(input), error: _i3.DispatchError.codec.decode(input)); - } - - /// u32 - final int index; - - /// DispatchError - final _i3.DispatchError error; - - @override - Map> toJson() => { - 'BatchInterrupted': {'index': index, 'error': error.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i1.U32Codec.codec.sizeHint(index); - size = size + _i3.DispatchError.codec.sizeHint(error); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(0, output); - _i1.U32Codec.codec.encodeTo(index, output); - _i3.DispatchError.codec.encodeTo(error, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is BatchInterrupted && other.index == index && other.error == error; - - @override - int get hashCode => Object.hash(index, error); -} - -/// Batch of dispatches completed fully with no error. -class BatchCompleted extends Event { - const BatchCompleted(); - - @override - Map toJson() => {'BatchCompleted': null}; - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(1, output); - } - - @override - bool operator ==(Object other) => other is BatchCompleted; - - @override - int get hashCode => runtimeType.hashCode; -} - -/// Batch of dispatches completed but has errors. -class BatchCompletedWithErrors extends Event { - const BatchCompletedWithErrors(); - - @override - Map toJson() => {'BatchCompletedWithErrors': null}; - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(2, output); - } - - @override - bool operator ==(Object other) => other is BatchCompletedWithErrors; - - @override - int get hashCode => runtimeType.hashCode; -} - -/// A single item within a Batch of dispatches has completed with no error. -class ItemCompleted extends Event { - const ItemCompleted(); - - @override - Map toJson() => {'ItemCompleted': null}; - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(3, output); - } - - @override - bool operator ==(Object other) => other is ItemCompleted; - - @override - int get hashCode => runtimeType.hashCode; -} - -/// A single item within a Batch of dispatches has completed with error. -class ItemFailed extends Event { - const ItemFailed({required this.error}); - - factory ItemFailed._decode(_i1.Input input) { - return ItemFailed(error: _i3.DispatchError.codec.decode(input)); - } - - /// DispatchError - final _i3.DispatchError error; - - @override - Map>> toJson() => { - 'ItemFailed': {'error': error.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.DispatchError.codec.sizeHint(error); - return size; + _i1.U8Codec.codec.encodeTo(value.codecIndex, output); } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(4, output); - _i3.DispatchError.codec.encodeTo(error, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is ItemFailed && other.error == error; - - @override - int get hashCode => error.hashCode; -} - -/// A call was dispatched. -class DispatchedAs extends Event { - const DispatchedAs({required this.result}); - - factory DispatchedAs._decode(_i1.Input input) { - return DispatchedAs( - result: const _i1.ResultCodec( - _i1.NullCodec.codec, - _i3.DispatchError.codec, - ).decode(input), - ); - } - - /// DispatchResult - final _i1.Result result; - - @override - Map>> toJson() => { - 'DispatchedAs': {'result': result.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = - size + - const _i1.ResultCodec( - _i1.NullCodec.codec, - _i3.DispatchError.codec, - ).sizeHint(result); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(5, output); - const _i1.ResultCodec( - _i1.NullCodec.codec, - _i3.DispatchError.codec, - ).encodeTo(result, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is DispatchedAs && other.result == result; - - @override - int get hashCode => result.hashCode; -} - -/// Main call was dispatched. -class IfElseMainSuccess extends Event { - const IfElseMainSuccess(); - - @override - Map toJson() => {'IfElseMainSuccess': null}; - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(6, output); - } - - @override - bool operator ==(Object other) => other is IfElseMainSuccess; - - @override - int get hashCode => runtimeType.hashCode; -} - -/// The fallback call was dispatched. -class IfElseFallbackCalled extends Event { - const IfElseFallbackCalled({required this.mainError}); - - factory IfElseFallbackCalled._decode(_i1.Input input) { - return IfElseFallbackCalled(mainError: _i3.DispatchError.codec.decode(input)); - } - - /// DispatchError - final _i3.DispatchError mainError; - - @override - Map>> toJson() => { - 'IfElseFallbackCalled': {'mainError': mainError.toJson()}, - }; - - int _sizeHint() { - int size = 1; - size = size + _i3.DispatchError.codec.sizeHint(mainError); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(7, output); - _i3.DispatchError.codec.encodeTo(mainError, output); - } - - @override - bool operator ==(Object other) => - identical(this, other) || other is IfElseFallbackCalled && other.mainError == mainError; - - @override - int get hashCode => mainError.hashCode; } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/call.dart b/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/call.dart index 3329f0b20..bd9962ea3 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/call.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/call.dart @@ -117,7 +117,9 @@ class $CallCodec with _i1.Codec { /// Pay the largest valid claim on `schedule_id` to its beneficiary. Payouts are /// rounded down to [`Config::PayoutQuantum`], must meet [`Config::MinimumPayout`], /// and reserve at least one minimum-sized final claim unless the schedule is fully -/// vested. +/// vested. Non-final payouts are further rounded down to +/// [`NON_FINAL_PAYOUT_QUANTA`] leaf quanta; the leftover stays on the schedule +/// until a later claim or the exact final payout. /// /// Permissionless: any signed account may call this for any schedule; the payout /// always goes to the stored beneficiary. This is the only claim path for @@ -235,13 +237,11 @@ class CreateSchedule extends Call { int get hashCode => Object.hash(beneficiary, start, cliff, end, total); } -/// End a schedule early: the still-unpaid vested part (rounded down to a -/// [`Config::PayoutQuantum`] multiple) goes to the beneficiary, everything else -/// this schedule still holds — the unvested remainder plus any sub-quantum -/// vested dust — returns to the treasury, and the schedule is removed. The -/// treasury is signature-controlled and needs no wormhole leaf, so dust is safe -/// there but would be stranded on a keyless beneficiary. A non-zero beneficiary -/// payout below [`Config::MinimumPayout`] is rejected without ending the schedule. +/// End a schedule early: the still-unpaid vested part (rounded to the nearest +/// [`Config::PayoutQuantum`]) goes to the beneficiary if it meets +/// [`Config::MinimumPayout`]; otherwise that sliver is refunded with the +/// unvested remainder. The treasury is signature-controlled and needs no +/// wormhole leaf, so the refund is not quantized and never blocks ending. class EndSchedule extends Call { const EndSchedule({required this.scheduleId}); @@ -275,8 +275,12 @@ class EndSchedule extends Call { int get hashCode => scheduleId.hashCode; } -/// Settle any payout a permissionless claim could currently force, then change the -/// beneficiary. This makes retargeting independent of claim transaction ordering. +/// Change the schedule's beneficiary without paying anything out. A retarget +/// replaces the wallet of the *same* grantee (lost-key remedy): the old address +/// may be lost or stolen, so settling it would burn funds or pay the thief. +/// Everything vested but unclaimed stays on the schedule and goes to the new +/// wallet at its next claim. (A permissionless claim landing before the +/// retarget still pays the old address, so rotate promptly.) class RetargetSchedule extends Call { const RetargetSchedule({required this.scheduleId, required this.newBeneficiary}); diff --git a/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/error.dart index 293eded58..d5b00952a 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/error.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/error.dart @@ -24,22 +24,19 @@ enum Error { /// entire remainder has vested. claimWouldLeaveDust('ClaimWouldLeaveDust', 4), - /// Ending now would emit a non-zero beneficiary payout below the minimum. - payoutBelowMinimum('PayoutBelowMinimum', 5), - /// The treasury account is not configured or aliases the vesting pot. - treasuryNotConfigured('TreasuryNotConfigured', 6), + treasuryNotConfigured('TreasuryNotConfigured', 5), /// The pot does not hold its existential-deposit buffer; endow it first. - potUnderfunded('PotUnderfunded', 7), + potUnderfunded('PotUnderfunded', 6), /// The beneficiary must not be the pot, and retargeting must change the account. - invalidBeneficiary('InvalidBeneficiary', 8), + invalidBeneficiary('InvalidBeneficiary', 7), /// The proof recorder reported the payout credit as dropped: no wormhole leaf /// was created, so the payout is rolled back rather than finalized without the /// proof material a keyless beneficiary needs to exit. - payoutProofNotRecorded('PayoutProofNotRecorded', 9); + payoutProofNotRecorded('PayoutProofNotRecorded', 8); const Error(this.variantName, this.codecIndex); @@ -78,14 +75,12 @@ class $ErrorCodec with _i1.Codec { case 4: return Error.claimWouldLeaveDust; case 5: - return Error.payoutBelowMinimum; - case 6: return Error.treasuryNotConfigured; - case 7: + case 6: return Error.potUnderfunded; - case 8: + case 7: return Error.invalidBeneficiary; - case 9: + case 8: return Error.payoutProofNotRecorded; default: throw Exception('Error: Invalid variant index: "$index"'); diff --git a/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/event.dart b/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/event.dart index 54f1ab094..55ecc66f9 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/event.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_vesting/pallet/event.dart @@ -74,14 +74,8 @@ class $Event { required BigInt scheduleId, required _i3.AccountId32 oldBeneficiary, required _i3.AccountId32 newBeneficiary, - required BigInt vestedPaid, }) { - return ScheduleRetargeted( - scheduleId: scheduleId, - oldBeneficiary: oldBeneficiary, - newBeneficiary: newBeneficiary, - vestedPaid: vestedPaid, - ); + return ScheduleRetargeted(scheduleId: scheduleId, oldBeneficiary: oldBeneficiary, newBeneficiary: newBeneficiary); } } @@ -354,21 +348,17 @@ class ScheduleEnded extends Event { int get hashCode => Object.hash(scheduleId, beneficiary, vestedPaid, unvestedReturned); } -/// A schedule's beneficiary was changed after settling any currently claimable payout. +/// A schedule's beneficiary was changed. Nothing was paid out: the retarget +/// replaces the same grantee's wallet, so the accrued entitlement follows the +/// schedule to the new address. class ScheduleRetargeted extends Event { - const ScheduleRetargeted({ - required this.scheduleId, - required this.oldBeneficiary, - required this.newBeneficiary, - required this.vestedPaid, - }); + const ScheduleRetargeted({required this.scheduleId, required this.oldBeneficiary, required this.newBeneficiary}); factory ScheduleRetargeted._decode(_i1.Input input) { return ScheduleRetargeted( scheduleId: _i1.U64Codec.codec.decode(input), oldBeneficiary: const _i1.U8ArrayCodec(32).decode(input), newBeneficiary: const _i1.U8ArrayCodec(32).decode(input), - vestedPaid: _i1.U128Codec.codec.decode(input), ); } @@ -381,16 +371,12 @@ class ScheduleRetargeted extends Event { /// T::AccountId final _i3.AccountId32 newBeneficiary; - /// BalanceOf - final BigInt vestedPaid; - @override Map> toJson() => { 'ScheduleRetargeted': { 'scheduleId': scheduleId, 'oldBeneficiary': oldBeneficiary.toList(), 'newBeneficiary': newBeneficiary.toList(), - 'vestedPaid': vestedPaid, }, }; @@ -399,7 +385,6 @@ class ScheduleRetargeted extends Event { size = size + _i1.U64Codec.codec.sizeHint(scheduleId); size = size + const _i3.AccountId32Codec().sizeHint(oldBeneficiary); size = size + const _i3.AccountId32Codec().sizeHint(newBeneficiary); - size = size + _i1.U128Codec.codec.sizeHint(vestedPaid); return size; } @@ -408,7 +393,6 @@ class ScheduleRetargeted extends Event { _i1.U64Codec.codec.encodeTo(scheduleId, output); const _i1.U8ArrayCodec(32).encodeTo(oldBeneficiary, output); const _i1.U8ArrayCodec(32).encodeTo(newBeneficiary, output); - _i1.U128Codec.codec.encodeTo(vestedPaid, output); } @override @@ -417,9 +401,8 @@ class ScheduleRetargeted extends Event { other is ScheduleRetargeted && other.scheduleId == scheduleId && _i4.listsEqual(other.oldBeneficiary, oldBeneficiary) && - _i4.listsEqual(other.newBeneficiary, newBeneficiary) && - other.vestedPaid == vestedPaid; + _i4.listsEqual(other.newBeneficiary, newBeneficiary); @override - int get hashCode => Object.hash(scheduleId, oldBeneficiary, newBeneficiary, vestedPaid); + int get hashCode => Object.hash(scheduleId, oldBeneficiary, newBeneficiary); } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_wormhole/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_wormhole/pallet/error.dart index 5cb100424..5bd63115e 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_wormhole/pallet/error.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_wormhole/pallet/error.dart @@ -12,9 +12,9 @@ enum Error { /// proof does). nullifierAlreadyUsed('NullifierAlreadyUsed', 1), - /// The bundle contains only dummy (all-zero) padding segments, so there is - /// nothing to exit. Distinct from [`Error::NullifierAlreadyUsed`], which is a - /// replay of real segments. + /// The bundle has nothing to settle: only dummy (all-zero) padding, or + /// every valid segment exits zero. Distinct from [`Error::NullifierAlreadyUsed`], + /// which is a replay of real segments. noValidSegments('NoValidSegments', 2), blockNotFound('BlockNotFound', 3), verifierNotAvailable('VerifierNotAvailable', 4), diff --git a/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/error.dart b/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/error.dart index de8e32a42..638934490 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/error.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/error.dart @@ -9,7 +9,11 @@ enum Error { leafIndexOutOfBounds('LeafIndexOutOfBounds', 0), /// Leaf not found. - leafNotFound('LeafNotFound', 1); + leafNotFound('LeafNotFound', 1), + + /// Leaf was appended this block and is not yet folded into the root; it + /// becomes provable once the block is finalized. + leafNotYetSettled('LeafNotYetSettled', 2); const Error(this.variantName, this.codecIndex); @@ -41,6 +45,8 @@ class $ErrorCodec with _i1.Codec { return Error.leafIndexOutOfBounds; case 1: return Error.leafNotFound; + case 2: + return Error.leafNotYetSettled; default: throw Exception('Error: Invalid variant index: "$index"'); } diff --git a/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/event.dart b/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/event.dart index 0f235cacd..ba34a08ba 100644 --- a/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/event.dart +++ b/quantus_sdk/lib/generated/planck/types/pallet_zk_tree/pallet/event.dart @@ -2,7 +2,6 @@ import 'dart:typed_data' as _i2; import 'package:polkadart/scale_codec.dart' as _i1; -import 'package:quiver/collection.dart' as _i3; /// The `Event` enum of this pallet abstract class Event { @@ -32,8 +31,8 @@ abstract class Event { class $Event { const $Event(); - LeafInserted leafInserted({required BigInt index, required List leafHash, required List newRoot}) { - return LeafInserted(index: index, leafHash: leafHash, newRoot: newRoot); + LeafInserted leafInserted({required BigInt index}) { + return LeafInserted(index: index); } TreeGrew treeGrew({required int newDepth}) { @@ -84,57 +83,42 @@ class $EventCodec with _i1.Codec { } } -/// A new leaf was inserted into the tree. +/// A new leaf was inserted into the tree. The root including this leaf is +/// computed at the end of the block and published in the block header. The +/// leaf hash is deliberately not included: it is derivable from `Leaves` +/// (and served by the RPC), and hashing it here would double the per-leaf +/// Poseidon work the batched settlement saves. class LeafInserted extends Event { - const LeafInserted({required this.index, required this.leafHash, required this.newRoot}); + const LeafInserted({required this.index}); factory LeafInserted._decode(_i1.Input input) { - return LeafInserted( - index: _i1.U64Codec.codec.decode(input), - leafHash: const _i1.U8ArrayCodec(32).decode(input), - newRoot: const _i1.U8ArrayCodec(32).decode(input), - ); + return LeafInserted(index: _i1.U64Codec.codec.decode(input)); } /// u64 final BigInt index; - /// Hash256 - final List leafHash; - - /// Hash256 - final List newRoot; - @override - Map> toJson() => { - 'LeafInserted': {'index': index, 'leafHash': leafHash.toList(), 'newRoot': newRoot.toList()}, + Map> toJson() => { + 'LeafInserted': {'index': index}, }; int _sizeHint() { int size = 1; size = size + _i1.U64Codec.codec.sizeHint(index); - size = size + const _i1.U8ArrayCodec(32).sizeHint(leafHash); - size = size + const _i1.U8ArrayCodec(32).sizeHint(newRoot); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(0, output); _i1.U64Codec.codec.encodeTo(index, output); - const _i1.U8ArrayCodec(32).encodeTo(leafHash, output); - const _i1.U8ArrayCodec(32).encodeTo(newRoot, output); } @override - bool operator ==(Object other) => - identical(this, other) || - other is LeafInserted && - other.index == index && - _i3.listsEqual(other.leafHash, leafHash) && - _i3.listsEqual(other.newRoot, newRoot); + bool operator ==(Object other) => identical(this, other) || other is LeafInserted && other.index == index; @override - int get hashCode => Object.hash(index, leafHash, newRoot); + int get hashCode => index.hashCode; } /// Tree depth increased. diff --git a/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_call.dart b/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_call.dart index aac166d9a..3bf0f6390 100644 --- a/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_call.dart +++ b/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_call.dart @@ -5,17 +5,16 @@ import 'package:polkadart/scale_codec.dart' as _i1; import '../frame_system/pallet/call.dart' as _i3; import '../pallet_balances/pallet/call.dart' as _i5; -import '../pallet_multisig/pallet/call.dart' as _i13; +import '../pallet_multisig/pallet/call.dart' as _i12; import '../pallet_preimage/pallet/call.dart' as _i6; import '../pallet_ranked_collective/pallet/call.dart' as _i9; -import '../pallet_recovery/pallet/call.dart' as _i12; import '../pallet_referenda/pallet/call.dart' as _i10; import '../pallet_reversible_transfers/pallet/call.dart' as _i8; import '../pallet_timestamp/pallet/call.dart' as _i4; import '../pallet_treasury/pallet/call.dart' as _i11; import '../pallet_utility/pallet/call.dart' as _i7; -import '../pallet_vesting/pallet/call.dart' as _i15; -import '../pallet_wormhole/pallet/call.dart' as _i14; +import '../pallet_vesting/pallet/call.dart' as _i14; +import '../pallet_wormhole/pallet/call.dart' as _i13; abstract class RuntimeCall { const RuntimeCall(); @@ -38,7 +37,7 @@ abstract class RuntimeCall { return codec.sizeHint(this); } - Map> toJson(); + Map>> toJson(); } class $RuntimeCall { @@ -80,19 +79,15 @@ class $RuntimeCall { return TreasuryPallet(value0); } - Recovery recovery(_i12.Call value0) { - return Recovery(value0); - } - - Multisig multisig(_i13.Call value0) { + Multisig multisig(_i12.Call value0) { return Multisig(value0); } - Wormhole wormhole(_i14.Call value0) { + Wormhole wormhole(_i13.Call value0) { return Wormhole(value0); } - Vesting vesting(_i15.Call value0) { + Vesting vesting(_i14.Call value0) { return Vesting(value0); } } @@ -122,8 +117,6 @@ class $RuntimeCallCodec with _i1.Codec { return TechReferenda._decode(input); case 15: return TreasuryPallet._decode(input); - case 16: - return Recovery._decode(input); case 19: return Multisig._decode(input); case 20: @@ -165,9 +158,6 @@ class $RuntimeCallCodec with _i1.Codec { case TreasuryPallet: (value as TreasuryPallet).encodeTo(output); break; - case Recovery: - (value as Recovery).encodeTo(output); - break; case Multisig: (value as Multisig).encodeTo(output); break; @@ -203,8 +193,6 @@ class $RuntimeCallCodec with _i1.Codec { return (value as TechReferenda)._sizeHint(); case TreasuryPallet: return (value as TreasuryPallet)._sizeHint(); - case Recovery: - return (value as Recovery)._sizeHint(); case Multisig: return (value as Multisig)._sizeHint(); case Wormhole: @@ -357,7 +345,7 @@ class Utility extends RuntimeCall { final _i7.Call value0; @override - Map>> toJson() => {'Utility': value0.toJson()}; + Map>>>> toJson() => {'Utility': value0.toJson()}; int _sizeHint() { int size = 1; @@ -485,7 +473,7 @@ class TreasuryPallet extends RuntimeCall { final _i11.Call value0; @override - Map>> toJson() => {'TreasuryPallet': value0.toJson()}; + Map>>> toJson() => {'TreasuryPallet': value0.toJson()}; int _sizeHint() { int size = 1; @@ -505,61 +493,29 @@ class TreasuryPallet extends RuntimeCall { int get hashCode => value0.hashCode; } -class Recovery extends RuntimeCall { - const Recovery(this.value0); - - factory Recovery._decode(_i1.Input input) { - return Recovery(_i12.Call.codec.decode(input)); - } - - /// self::sp_api_hidden_includes_construct_runtime::hidden_include::dispatch - ///::CallableCallFor - final _i12.Call value0; - - @override - Map> toJson() => {'Recovery': value0.toJson()}; - - int _sizeHint() { - int size = 1; - size = size + _i12.Call.codec.sizeHint(value0); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(16, output); - _i12.Call.codec.encodeTo(value0, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is Recovery && other.value0 == value0; - - @override - int get hashCode => value0.hashCode; -} - class Multisig extends RuntimeCall { const Multisig(this.value0); factory Multisig._decode(_i1.Input input) { - return Multisig(_i13.Call.codec.decode(input)); + return Multisig(_i12.Call.codec.decode(input)); } /// self::sp_api_hidden_includes_construct_runtime::hidden_include::dispatch ///::CallableCallFor - final _i13.Call value0; + final _i12.Call value0; @override Map>> toJson() => {'Multisig': value0.toJson()}; int _sizeHint() { int size = 1; - size = size + _i13.Call.codec.sizeHint(value0); + size = size + _i12.Call.codec.sizeHint(value0); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(19, output); - _i13.Call.codec.encodeTo(value0, output); + _i12.Call.codec.encodeTo(value0, output); } @override @@ -573,25 +529,25 @@ class Wormhole extends RuntimeCall { const Wormhole(this.value0); factory Wormhole._decode(_i1.Input input) { - return Wormhole(_i14.Call.codec.decode(input)); + return Wormhole(_i13.Call.codec.decode(input)); } /// self::sp_api_hidden_includes_construct_runtime::hidden_include::dispatch ///::CallableCallFor - final _i14.Call value0; + final _i13.Call value0; @override Map>>> toJson() => {'Wormhole': value0.toJson()}; int _sizeHint() { int size = 1; - size = size + _i14.Call.codec.sizeHint(value0); + size = size + _i13.Call.codec.sizeHint(value0); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(20, output); - _i14.Call.codec.encodeTo(value0, output); + _i13.Call.codec.encodeTo(value0, output); } @override @@ -605,25 +561,25 @@ class Vesting extends RuntimeCall { const Vesting(this.value0); factory Vesting._decode(_i1.Input input) { - return Vesting(_i15.Call.codec.decode(input)); + return Vesting(_i14.Call.codec.decode(input)); } /// self::sp_api_hidden_includes_construct_runtime::hidden_include::dispatch ///::CallableCallFor - final _i15.Call value0; + final _i14.Call value0; @override Map>> toJson() => {'Vesting': value0.toJson()}; int _sizeHint() { int size = 1; - size = size + _i15.Call.codec.sizeHint(value0); + size = size + _i14.Call.codec.sizeHint(value0); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(22, output); - _i15.Call.codec.encodeTo(value0, output); + _i14.Call.codec.encodeTo(value0, output); } @override diff --git a/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_event.dart b/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_event.dart index 7a950cc19..3f16c89bb 100644 --- a/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_event.dart +++ b/quantus_sdk/lib/generated/planck/types/quantus_runtime/runtime_event.dart @@ -6,20 +6,19 @@ import 'package:polkadart/scale_codec.dart' as _i1; import '../frame_system/pallet/event.dart' as _i3; import '../pallet_balances/pallet/event.dart' as _i4; import '../pallet_mining_rewards/pallet/event.dart' as _i7; -import '../pallet_multisig/pallet/event.dart' as _i16; +import '../pallet_multisig/pallet/event.dart' as _i15; import '../pallet_preimage/pallet/event.dart' as _i8; import '../pallet_qpow/pallet/event.dart' as _i6; import '../pallet_ranked_collective/pallet/event.dart' as _i12; -import '../pallet_recovery/pallet/event.dart' as _i15; import '../pallet_referenda/pallet/event.dart' as _i13; import '../pallet_reversible_transfers/pallet/event.dart' as _i11; import '../pallet_scheduler/pallet/event.dart' as _i9; import '../pallet_transaction_payment/pallet/event.dart' as _i5; import '../pallet_treasury/pallet/event.dart' as _i14; import '../pallet_utility/pallet/event.dart' as _i10; -import '../pallet_vesting/pallet/event.dart' as _i19; -import '../pallet_wormhole/pallet/event.dart' as _i17; -import '../pallet_zk_tree/pallet/event.dart' as _i18; +import '../pallet_vesting/pallet/event.dart' as _i18; +import '../pallet_wormhole/pallet/event.dart' as _i16; +import '../pallet_zk_tree/pallet/event.dart' as _i17; abstract class RuntimeEvent { const RuntimeEvent(); @@ -42,7 +41,7 @@ abstract class RuntimeEvent { return codec.sizeHint(this); } - Map> toJson(); + Map toJson(); } class $RuntimeEvent { @@ -96,23 +95,19 @@ class $RuntimeEvent { return TreasuryPallet(value0); } - Recovery recovery(_i15.Event value0) { - return Recovery(value0); - } - - Multisig multisig(_i16.Event value0) { + Multisig multisig(_i15.Event value0) { return Multisig(value0); } - Wormhole wormhole(_i17.Event value0) { + Wormhole wormhole(_i16.Event value0) { return Wormhole(value0); } - ZkTree zkTree(_i18.Event value0) { + ZkTree zkTree(_i17.Event value0) { return ZkTree(value0); } - Vesting vesting(_i19.Event value0) { + Vesting vesting(_i18.Event value0) { return Vesting(value0); } } @@ -148,8 +143,6 @@ class $RuntimeEventCodec with _i1.Codec { return TechReferenda._decode(input); case 15: return TreasuryPallet._decode(input); - case 16: - return Recovery._decode(input); case 19: return Multisig._decode(input); case 20: @@ -202,9 +195,6 @@ class $RuntimeEventCodec with _i1.Codec { case TreasuryPallet: (value as TreasuryPallet).encodeTo(output); break; - case Recovery: - (value as Recovery).encodeTo(output); - break; case Multisig: (value as Multisig).encodeTo(output); break; @@ -249,8 +239,6 @@ class $RuntimeEventCodec with _i1.Codec { return (value as TechReferenda)._sizeHint(); case TreasuryPallet: return (value as TreasuryPallet)._sizeHint(); - case Recovery: - return (value as Recovery)._sizeHint(); case Multisig: return (value as Multisig)._sizeHint(); case Wormhole: @@ -493,7 +481,7 @@ class Utility extends RuntimeEvent { final _i10.Event value0; @override - Map> toJson() => {'Utility': value0.toJson()}; + Map toJson() => {'Utility': value0.toJson()}; int _sizeHint() { int size = 1; @@ -617,7 +605,7 @@ class TreasuryPallet extends RuntimeEvent { final _i14.Event value0; @override - Map>> toJson() => {'TreasuryPallet': value0.toJson()}; + Map?>>> toJson() => {'TreasuryPallet': value0.toJson()}; int _sizeHint() { int size = 1; @@ -637,59 +625,28 @@ class TreasuryPallet extends RuntimeEvent { int get hashCode => value0.hashCode; } -class Recovery extends RuntimeEvent { - const Recovery(this.value0); - - factory Recovery._decode(_i1.Input input) { - return Recovery(_i15.Event.codec.decode(input)); - } - - /// pallet_recovery::Event - final _i15.Event value0; - - @override - Map>> toJson() => {'Recovery': value0.toJson()}; - - int _sizeHint() { - int size = 1; - size = size + _i15.Event.codec.sizeHint(value0); - return size; - } - - void encodeTo(_i1.Output output) { - _i1.U8Codec.codec.encodeTo(16, output); - _i15.Event.codec.encodeTo(value0, output); - } - - @override - bool operator ==(Object other) => identical(this, other) || other is Recovery && other.value0 == value0; - - @override - int get hashCode => value0.hashCode; -} - class Multisig extends RuntimeEvent { const Multisig(this.value0); factory Multisig._decode(_i1.Input input) { - return Multisig(_i16.Event.codec.decode(input)); + return Multisig(_i15.Event.codec.decode(input)); } /// pallet_multisig::Event - final _i16.Event value0; + final _i15.Event value0; @override Map>> toJson() => {'Multisig': value0.toJson()}; int _sizeHint() { int size = 1; - size = size + _i16.Event.codec.sizeHint(value0); + size = size + _i15.Event.codec.sizeHint(value0); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(19, output); - _i16.Event.codec.encodeTo(value0, output); + _i15.Event.codec.encodeTo(value0, output); } @override @@ -703,24 +660,24 @@ class Wormhole extends RuntimeEvent { const Wormhole(this.value0); factory Wormhole._decode(_i1.Input input) { - return Wormhole(_i17.Event.codec.decode(input)); + return Wormhole(_i16.Event.codec.decode(input)); } /// pallet_wormhole::Event - final _i17.Event value0; + final _i16.Event value0; @override Map>> toJson() => {'Wormhole': value0.toJson()}; int _sizeHint() { int size = 1; - size = size + _i17.Event.codec.sizeHint(value0); + size = size + _i16.Event.codec.sizeHint(value0); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(20, output); - _i17.Event.codec.encodeTo(value0, output); + _i16.Event.codec.encodeTo(value0, output); } @override @@ -734,24 +691,24 @@ class ZkTree extends RuntimeEvent { const ZkTree(this.value0); factory ZkTree._decode(_i1.Input input) { - return ZkTree(_i18.Event.codec.decode(input)); + return ZkTree(_i17.Event.codec.decode(input)); } /// pallet_zk_tree::Event - final _i18.Event value0; + final _i17.Event value0; @override Map>> toJson() => {'ZkTree': value0.toJson()}; int _sizeHint() { int size = 1; - size = size + _i18.Event.codec.sizeHint(value0); + size = size + _i17.Event.codec.sizeHint(value0); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(21, output); - _i18.Event.codec.encodeTo(value0, output); + _i17.Event.codec.encodeTo(value0, output); } @override @@ -765,24 +722,24 @@ class Vesting extends RuntimeEvent { const Vesting(this.value0); factory Vesting._decode(_i1.Input input) { - return Vesting(_i19.Event.codec.decode(input)); + return Vesting(_i18.Event.codec.decode(input)); } /// pallet_vesting::Event - final _i19.Event value0; + final _i18.Event value0; @override Map>> toJson() => {'Vesting': value0.toJson()}; int _sizeHint() { int size = 1; - size = size + _i19.Event.codec.sizeHint(value0); + size = size + _i18.Event.codec.sizeHint(value0); return size; } void encodeTo(_i1.Output output) { _i1.U8Codec.codec.encodeTo(22, output); - _i19.Event.codec.encodeTo(value0, output); + _i18.Event.codec.encodeTo(value0, output); } @override diff --git a/quantus_sdk/lib/quantus_sdk.dart b/quantus_sdk/lib/quantus_sdk.dart index 37ba92a1a..d28d558c2 100644 --- a/quantus_sdk/lib/quantus_sdk.dart +++ b/quantus_sdk/lib/quantus_sdk.dart @@ -65,7 +65,6 @@ export 'src/services/network/redundant_endpoint.dart'; export 'src/services/locale_number_config.dart'; export 'src/services/number_formatting_service.dart'; export 'src/services/recent_addresses_service.dart'; -export 'src/services/recovery_service.dart'; export 'src/services/reversible_transfers_service.dart'; export 'src/services/settings_service.dart'; export 'src/services/substrate_service.dart'; diff --git a/quantus_sdk/lib/src/chain/call_decoder.dart b/quantus_sdk/lib/src/chain/call_decoder.dart index 3dd0120dc..c45f3a3c5 100644 --- a/quantus_sdk/lib/src/chain/call_decoder.dart +++ b/quantus_sdk/lib/src/chain/call_decoder.dart @@ -29,7 +29,6 @@ import 'package:quantus_sdk/generated/planck/types/pallet_balances/pallet/call.d import 'package:quantus_sdk/generated/planck/types/pallet_multisig/pallet/call.dart' as multisig; import 'package:quantus_sdk/generated/planck/types/pallet_preimage/pallet/call.dart' as preimage; import 'package:quantus_sdk/generated/planck/types/pallet_ranked_collective/pallet/call.dart' as collective; -import 'package:quantus_sdk/generated/planck/types/pallet_recovery/pallet/call.dart' as recovery; import 'package:quantus_sdk/generated/planck/types/pallet_referenda/pallet/call.dart' as referenda; import 'package:quantus_sdk/generated/planck/types/pallet_reversible_transfers/pallet/call.dart' as reversible; import 'package:quantus_sdk/generated/planck/types/pallet_treasury/pallet/call.dart' as treasury; @@ -44,18 +43,37 @@ import 'package:quantus_sdk/src/services/datetime_formatting_service.dart'; class CallDecoder { const CallDecoder._(); + /// Largest inner call a multisig proposal may carry, mirroring the runtime's + /// `pallet_multisig::Config::MaxCallSize` (`BoundedVec`, 10 KiB). + /// + /// Deliberately the chain's number rather than a tighter one of our own: a limit + /// below it would refuse proposals the chain accepts, leaving a multisig no cold + /// signer could act on. + static const int maxCallBytes = 10 * 1024; + + /// Throws when a call of [length] bytes is larger than a signer will review. + static void checkCallSize(int length) { + if (length > maxCallBytes) { + throw FormatException('Call is $length bytes, over the $maxCallBytes byte review limit'); + } + } + /// Decodes SCALE-encoded call bytes, requiring an exact fit. /// /// Trailing bytes mean the sender and this decoder disagree about the call's /// shape, so the result cannot be trusted for display — throw instead. - static DecodedCall decodeBytes(List bytes) { + static DecodedCall decodeBytes(List bytes) => describe(decodeRuntimeCall(bytes)); + + /// Decodes SCALE-encoded call bytes into the runtime call itself, for callers + /// that resubmit them (`multisig.execute`) rather than only display them. + static runtime.RuntimeCall decodeRuntimeCall(List bytes) { final input = Input.fromBytes(Uint8List.fromList(bytes)); final call = runtime.RuntimeCall.codec.decode(input); final remaining = input.remainingLength ?? 0; if (remaining != 0) { throw FormatException('$remaining trailing bytes after nested call'); } - return describe(call); + return call; } /// Describes [call] as a display tree carrying every one of its parameters. @@ -69,7 +87,6 @@ class CallDecoder { runtime.TechReferenda(:final value0) => _referenda(value0), runtime.TreasuryPallet(:final value0) => _treasury(value0), runtime.Utility(:final value0) => _utility(value0), - runtime.Recovery(:final value0) => _recovery(value0), runtime.System(:final value0) => _system(value0), _ => _generic(call), }; @@ -93,44 +110,12 @@ class CallDecoder { _boolField('Keep account alive', keepAlive), ], ); - case balances.ForceTransfer(:final source, :final dest, :final value): - final destination = _addressField('Destination', dest); - final amount = AmountField('Amount', value); - return DecodedCall( - pallet: 'Balances', - call: 'force_transfer', - fields: [_addressField('Source', source), destination, amount], - summary: _transferSummary(destination, amount), - ); - case balances.ForceUnreserve(:final who, :final amount): - return DecodedCall( - pallet: 'Balances', - call: 'force_unreserve', - fields: [_addressField('Account', who), AmountField('Amount', amount)], - ); - case balances.ForceSetBalance(:final who, :final newFree): - return DecodedCall( - pallet: 'Balances', - call: 'force_set_balance', - fields: [_addressField('Account', who), AmountField('New free balance', newFree)], - ); - case balances.ForceAdjustTotalIssuance(:final direction, :final delta): - return DecodedCall( - pallet: 'Balances', - call: 'force_adjust_total_issuance', - fields: [ - ValueField('Direction', direction.variantName, kind: ValueKind.text), - AmountField('Delta', delta), - ], - ); case balances.Burn(:final value, :final keepAlive): return DecodedCall( pallet: 'Balances', call: 'burn', fields: [AmountField('Amount', value), _boolField('Keep account alive', keepAlive)], ); - case balances.UpgradeAccounts(:final who): - return DecodedCall(pallet: 'Balances', call: 'upgrade_accounts', fields: [_accountListField('Accounts', who)]); default: return _generic(runtime.Balances(call)); } @@ -408,14 +393,6 @@ class CallDecoder { call: 'set_treasury_account', fields: [_accountField('Treasury account', account)], ); - case treasury.SetTreasuryPortion(:final portion): - // Permill: parts per million. - final percent = (portion / 10000).toStringAsFixed(4); - return DecodedCall( - pallet: 'TreasuryPallet', - call: 'set_treasury_portion', - fields: [ValueField('Portion', '$percent% ($portion per million)', kind: ValueKind.number)], - ); default: return _generic(runtime.TreasuryPallet(call)); } @@ -425,48 +402,8 @@ class CallDecoder { static DecodedCall _utility(utility.Call call) { switch (call) { - case utility.Batch(:final calls): - return _batch('batch', calls); case utility.BatchAll(:final calls): return _batch('batch_all', calls); - case utility.ForceBatch(:final calls): - return _batch('force_batch', calls); - case utility.AsDerivative(:final index, :final call): - final inner = describe(call); - return DecodedCall( - pallet: 'Utility', - call: 'as_derivative', - fields: [ - ValueField('Derivative index', '$index', kind: ValueKind.number), - NestedCallField('Call', inner), - ], - summary: inner.summary, - ); - case utility.DispatchAs(:final asOrigin, :final call): - return _dispatchAs('dispatch_as', asOrigin, call); - case utility.DispatchAsFallible(:final asOrigin, :final call): - return _dispatchAs('dispatch_as_fallible', asOrigin, call); - case utility.WithWeight(:final call, :final weight): - final inner = describe(call); - return DecodedCall( - pallet: 'Utility', - call: 'with_weight', - fields: [ - NestedCallField('Call', inner), - ValueField('Weight', 'ref time ${weight.refTime}, proof size ${weight.proofSize}', kind: ValueKind.number), - ], - summary: inner.summary, - ); - case utility.IfElse(:final main, :final fallback): - return DecodedCall( - pallet: 'Utility', - call: 'if_else', - fields: [ - NestedCallField('Primary call', describe(main)), - NestedCallField('Fallback call', describe(fallback)), - ], - summary: describe(main).summary, - ); default: return _generic(runtime.Utility(call)); } @@ -483,72 +420,6 @@ class CallDecoder { ); } - static DecodedCall _dispatchAs(String name, origin_caller.OriginCaller asOrigin, runtime.RuntimeCall call) { - final inner = describe(call); - return DecodedCall( - pallet: 'Utility', - call: name, - fields: [ - ValueField('Dispatch origin', _origin(asOrigin), kind: ValueKind.text), - NestedCallField('Call', inner), - ], - summary: inner.summary, - ); - } - - static DecodedCall _recovery(recovery.Call call) { - switch (call) { - case recovery.AsRecovered(:final account, :final call): - final inner = describe(call); - return DecodedCall( - pallet: 'Recovery', - call: 'as_recovered', - fields: [_addressField('Recovered account', account), NestedCallField('Call', inner)], - summary: inner.summary, - ); - case recovery.CreateRecovery(:final friends, :final threshold, :final delayPeriod): - return DecodedCall( - pallet: 'Recovery', - call: 'create_recovery', - fields: [ - _accountListField('Friends', friends), - ValueField('Threshold', '$threshold of ${friends.length}', kind: ValueKind.number), - ValueField('Waiting period', '$delayPeriod blocks', kind: ValueKind.blockOrTime), - ], - ); - case recovery.SetRecovered(:final lost, :final rescuer): - return DecodedCall( - pallet: 'Recovery', - call: 'set_recovered', - fields: [_addressField('Lost account', lost), _addressField('Rescuer', rescuer)], - ); - case recovery.VouchRecovery(:final lost, :final rescuer): - return DecodedCall( - pallet: 'Recovery', - call: 'vouch_recovery', - fields: [_addressField('Lost account', lost), _addressField('Rescuer', rescuer)], - ); - case recovery.InitiateRecovery(:final account): - return DecodedCall( - pallet: 'Recovery', - call: 'initiate_recovery', - fields: [_addressField('Account to recover', account)], - ); - case recovery.ClaimRecovery(:final account): - return DecodedCall( - pallet: 'Recovery', - call: 'claim_recovery', - fields: [_addressField('Account to claim', account)], - ); - case recovery.CloseRecovery(:final rescuer): - return DecodedCall(pallet: 'Recovery', call: 'close_recovery', fields: [_addressField('Rescuer', rescuer)]); - case recovery.CancelRecovered(:final account): - return DecodedCall(pallet: 'Recovery', call: 'cancel_recovered', fields: [_addressField('Account', account)]); - default: - return _generic(runtime.Recovery(call)); - } - } - // ------------------------------------------------------------------ System static DecodedCall _system(system.Call call) { @@ -666,7 +537,7 @@ class CallDecoder { return DecodedCall(pallet: pallet, call: '', fields: const []); } final callName = inner.keys.first; - final args = inner[callName]; + final dynamic args = inner[callName]; final fields = []; if (args is Map) { diff --git a/quantus_sdk/lib/src/constants/app_constants.dart b/quantus_sdk/lib/src/constants/app_constants.dart index 747a26929..2cf463c75 100644 --- a/quantus_sdk/lib/src/constants/app_constants.dart +++ b/quantus_sdk/lib/src/constants/app_constants.dart @@ -65,8 +65,8 @@ class AppConstants { // from. A signing payload declaring a different spec version may decode // against shifted pallet/call indices, so signers warn loudly rather than // present a decode they cannot vouch for. Bump both when regenerating. - static const int bundledSpecVersion = 136; - static const int bundledTransactionVersion = 3; + static const int bundledSpecVersion = 147; + static const int bundledTransactionVersion = 6; // Reserved account index for the per-wallet encrypted (wormhole) account. // Kept high so it never collides with sequential transparent (BIP44) indices; diff --git a/quantus_sdk/lib/src/quantus_payload_parser.dart b/quantus_sdk/lib/src/quantus_payload_parser.dart index 1bf360239..095e108be 100644 --- a/quantus_sdk/lib/src/quantus_payload_parser.dart +++ b/quantus_sdk/lib/src/quantus_payload_parser.dart @@ -29,7 +29,7 @@ import 'package:quantus_sdk/src/chain/decoded_call.dart'; import 'package:quantus_sdk/src/constants/app_constants.dart'; /// Hard cap on the raw signing payload; every supported call is far below this. -const int maxPayloadBytes = 8 * 1024; +const int maxPayloadBytes = 12 * 1024; /// Networks this wallet will sign for, keyed by genesis hash (lowercase hex). /// A payload whose genesis hash is not listed here is rejected. diff --git a/quantus_sdk/lib/src/services/multisig_service.dart b/quantus_sdk/lib/src/services/multisig_service.dart index 97d1eaf13..7cc591ba7 100644 --- a/quantus_sdk/lib/src/services/multisig_service.dart +++ b/quantus_sdk/lib/src/services/multisig_service.dart @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:quantus_sdk/generated/planck/pallets/multisig.dart' show Constants, Txs; import 'package:quantus_sdk/generated/planck/planck.dart' show Planck; import 'package:quantus_sdk/generated/planck/types/quantus_runtime/runtime_call.dart'; +import 'package:quantus_sdk/src/chain/call_decoder.dart'; import 'package:quantus_sdk/src/constants/app_constants.dart'; import 'package:quantus_sdk/src/models/account.dart'; import 'package:quantus_sdk/src/models/json_dynamic_parse.dart'; @@ -374,6 +375,7 @@ class MultisigService { }) { final innerCall = BalancesService().getBalanceTransferCall(recipient, amount); final callBytes = innerCall.encode(); + CallDecoder.checkCallSize(callBytes.length); return const Txs().propose(multisigAddress: getAccountId32(msig.accountId), call: callBytes, expiry: expiryBlock); } @@ -417,6 +419,7 @@ class MultisigService { /// [call] must be the proposal's stored inner call bytes — see /// [fetchProposalCallBytes]. The chain rejects an approval whose bytes differ. Multisig buildApproveCall({required MultisigAccount msig, required int proposalId, required List call}) { + CallDecoder.checkCallSize(call.length); return const Txs().approve(multisigAddress: getAccountId32(msig.accountId), proposalId: proposalId, call: call); } @@ -449,17 +452,31 @@ class MultisigService { } /// Builds the `multisig.execute` runtime call for [proposalId]. - Multisig buildExecuteCall({required MultisigAccount msig, required int proposalId}) { - return const Txs().execute(multisigAddress: getAccountId32(msig.accountId), proposalId: proposalId); + /// + /// [call] must be the proposal's stored inner call bytes — see + /// [fetchProposalCallBytes]. The chain dispatches the submitted call only when + /// it re-encodes to those exact bytes, so the executor signs the call itself + /// rather than an opaque proposal id. + Multisig buildExecuteCall({required MultisigAccount msig, required int proposalId, required List call}) { + CallDecoder.checkCallSize(call.length); + return const Txs().execute( + multisigAddress: getAccountId32(msig.accountId), + proposalId: proposalId, + call: CallDecoder.decodeRuntimeCall(call), + ); } /// Estimates the network fee for executing [proposalId]. + /// + /// Fee scales with the inner call, so [callBytes] is fetched when not supplied. Future estimateExecuteFee({ required MultisigAccount msig, required Account signer, required int proposalId, + List? callBytes, }) async { - final call = buildExecuteCall(msig: msig, proposalId: proposalId); + final inner = callBytes ?? await fetchProposalCallBytes(msig: msig, proposalId: proposalId); + final call = buildExecuteCall(msig: msig, proposalId: proposalId, call: inner); final feeData = await _substrateService.getFeeForCall(signer, call); return feeData.fee; } @@ -469,8 +486,10 @@ class MultisigService { required MultisigAccount msig, required Account signer, required int proposalId, + List? callBytes, }) async { - final call = buildExecuteCall(msig: msig, proposalId: proposalId); + final inner = callBytes ?? await fetchProposalCallBytes(msig: msig, proposalId: proposalId); + final call = buildExecuteCall(msig: msig, proposalId: proposalId, call: inner); return _substrateService.submitExtrinsic(signer, call); } diff --git a/quantus_sdk/lib/src/services/recovery_service.dart b/quantus_sdk/lib/src/services/recovery_service.dart deleted file mode 100644 index 1406cd63a..000000000 --- a/quantus_sdk/lib/src/services/recovery_service.dart +++ /dev/null @@ -1,310 +0,0 @@ -import 'dart:async'; -import 'dart:typed_data'; - -import 'package:quantus_sdk/generated/planck/planck.dart'; -import 'package:quantus_sdk/generated/planck/types/pallet_recovery/active_recovery.dart'; -import 'package:quantus_sdk/generated/planck/types/pallet_recovery/recovery_config.dart'; -import 'package:quantus_sdk/generated/planck/types/sp_runtime/multiaddress/multi_address.dart' as multi_address; -import 'package:quantus_sdk/quantus_sdk.dart'; -import 'package:quantus_sdk/src/extensions/address_extension.dart'; -import 'package:quantus_sdk/src/rust/api/crypto.dart' as crypto; - -/// Service for managing account recovery functionality -class RecoveryService { - static final RecoveryService _instance = RecoveryService._internal(); - factory RecoveryService() => _instance; - RecoveryService._internal(); - - final SubstrateService _substrateService = SubstrateService(); - - final dummyQuantusApi = Planck.url(Uri.parse(AppConstants.rpcEndpoints[0])); - late final BigInt configDepositBase = dummyQuantusApi.constant.recovery.configDepositBase; - late final BigInt friendDepositFactor = dummyQuantusApi.constant.recovery.friendDepositFactor; - late final int maxFriends = dummyQuantusApi.constant.recovery.maxFriends; - late final BigInt recoveryDeposit = dummyQuantusApi.constant.recovery.recoveryDeposit; - - /// Create a recovery configuration for an account - /// This makes the account recoverable by trusted friends - Future createRecoveryConfig({ - required Account account, - required List friendAddresses, - required int threshold, - required int delayPeriod, - }) async { - try { - final quantusApi = Planck(_substrateService.provider!); - final friends = friendAddresses.map((addr) => crypto.ss58ToAccountId(s: addr)).toList(); - - // Create the call - final call = quantusApi.tx.recovery.createRecovery( - friends: friends, - threshold: threshold, - delayPeriod: delayPeriod, - ); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(account, call); - } catch (e) { - throw Exception('Failed to create recovery config: $e'); - } - } - - /// Initiate recovery process for a lost account - Future initiateRecovery({required Account rescuerAccount, required String lostAccountAddress}) async { - try { - final call = getInitiateRecoveryCall(lostAccountAddress); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(rescuerAccount, call); - } catch (e) { - throw Exception('Failed to initiate recovery: $e'); - } - } - - RuntimeCall getInitiateRecoveryCall(String lostAccountAddress) { - final quantusApi = Planck(_substrateService.provider!); - final lostAccount = const multi_address.$MultiAddress().id(crypto.ss58ToAccountId(s: lostAccountAddress)); - return quantusApi.tx.recovery.initiateRecovery(account: lostAccount); - } - - /// Vouch for an active recovery process (called by friends) - Future vouchForRecovery({ - required Account friendAccount, - required String lostAccountAddress, - required String rescuerAddress, - }) async { - try { - final call = getVouchRecoveryCall(lostAccountAddress, rescuerAddress); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(friendAccount, call); - } catch (e) { - throw Exception('Failed to vouch for recovery: $e'); - } - } - - RuntimeCall getVouchRecoveryCall(String lostAccountAddress, String rescuerAddress) { - final quantusApi = Planck(_substrateService.provider!); - final lostAccount = const multi_address.$MultiAddress().id(crypto.ss58ToAccountId(s: lostAccountAddress)); - final rescuer = const multi_address.$MultiAddress().id(crypto.ss58ToAccountId(s: rescuerAddress)); - return quantusApi.tx.recovery.vouchRecovery(lost: lostAccount, rescuer: rescuer); - } - - /// Claim recovery of a lost account (called by rescuer after threshold is met) - Future claimRecovery({required Account rescuerAccount, required String lostAccountAddress}) async { - try { - final call = getClaimRecoveryCall(lostAccountAddress); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(rescuerAccount, call); - } catch (e) { - throw Exception('Failed to claim recovery: $e'); - } - } - - RuntimeCall getClaimRecoveryCall(String lostAccountAddress) { - final quantusApi = Planck(_substrateService.provider!); - final lostAccount = const multi_address.$MultiAddress().id(crypto.ss58ToAccountId(s: lostAccountAddress)); - return quantusApi.tx.recovery.claimRecovery(account: lostAccount); - } - - /// Close an active recovery process (called by the lost account owner) - Future closeRecovery({required Account lostAccount, required String rescuerAddress}) async { - try { - final quantusApi = Planck(_substrateService.provider!); - final rescuer = const multi_address.$MultiAddress().id(crypto.ss58ToAccountId(s: rescuerAddress)); - - // Create the call - final call = quantusApi.tx.recovery.closeRecovery(rescuer: rescuer); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(lostAccount, call); - } catch (e) { - throw Exception('Failed to close recovery: $e'); - } - } - - /// Remove recovery configuration from account - Future removeRecoveryConfig({required Account senderAccount}) async { - try { - final quantusApi = Planck(_substrateService.provider!); - - // Create the call - final call = quantusApi.tx.recovery.removeRecovery(); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(senderAccount, call); - } catch (e) { - throw Exception('Failed to remove recovery config: $e'); - } - } - - /// Call a function as a recovered account (proxy call) - Future callAsRecovered({ - required Account rescuerAccount, - required String recoveredAccountAddress, - required RuntimeCall call, - }) async { - try { - final proxyCall = getAsRecoveredCall(recoveredAccountAddress, call); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(rescuerAccount, proxyCall); - } catch (e) { - throw Exception('Failed to call as recovered: $e'); - } - } - - RuntimeCall getAsRecoveredCall(String recoveredAccountAddress, RuntimeCall call) { - final quantusApi = Planck(_substrateService.provider!); - final recoveredAccount = const multi_address.$MultiAddress().id(crypto.ss58ToAccountId(s: recoveredAccountAddress)); - return quantusApi.tx.recovery.asRecovered(account: recoveredAccount, call: call); - } - - /// Cancel the ability to use a recovered account - Future cancelRecovered({required Account rescuerAccount, required String recoveredAccountAddress}) async { - try { - final quantusApi = Planck(_substrateService.provider!); - final recoveredAccount = const multi_address.$MultiAddress().id( - crypto.ss58ToAccountId(s: recoveredAccountAddress), - ); - - // Create the call - final call = quantusApi.tx.recovery.cancelRecovered(account: recoveredAccount); - - // Submit the transaction using substrate service - return await _substrateService.submitExtrinsic(rescuerAccount, call); - } catch (e) { - throw Exception('Failed to cancel recovered: $e'); - } - } - - /// Query recovery configuration for an account - Future getRecoveryConfig(String address) async { - try { - final quantusApi = Planck(_substrateService.provider!); - final accountId = crypto.ss58ToAccountId(s: address); - - return await quantusApi.query.recovery.recoverable(accountId); - } catch (e) { - throw Exception('Failed to get recovery config: $e'); - } - } - - /// Query active recovery process - Future getActiveRecovery(String lostAccountAddress, String rescuerAddress) async { - try { - final quantusApi = Planck(_substrateService.provider!); - final lostAccountId = crypto.ss58ToAccountId(s: lostAccountAddress); - final rescuerId = crypto.ss58ToAccountId(s: rescuerAddress); - - return await quantusApi.query.recovery.activeRecoveries(lostAccountId, rescuerId); - } catch (e) { - throw Exception('Failed to get active recovery: $e'); - } - } - - /// Check if an account can act as proxy for a recovered account - Future getProxyRecoveredAccount(String proxyAddress) async { - try { - final quantusApi = Planck(_substrateService.provider!); - final proxyId = crypto.ss58ToAccountId(s: proxyAddress); - - final recoveredAccountId = await quantusApi.query.recovery.proxy(proxyId); - // The storage map returns the final AccountId32, so encode it directly to - // SS58. crypto.toAccountId would incorrectly Poseidon-hash the - // already-derived account ID. - return recoveredAccountId != null - ? AddressExtension.ss58AddressFromBytes(Uint8List.fromList(recoveredAccountId)) - : null; - } catch (e) { - throw Exception('Failed to get proxy recovered account: $e'); - } - } - - /// Check if account has recovery configuration - Future hasRecoveryConfig(String address) async { - try { - final config = await getRecoveryConfig(address); - return config != null; - } catch (e) { - throw Exception('Failed to check recovery config: $e'); - } - } - - /// Check if recovery process is active - Future isRecoveryActive(String lostAccountAddress, String rescuerAddress) async { - try { - final activeRecovery = await getActiveRecovery(lostAccountAddress, rescuerAddress); - return activeRecovery != null; - } catch (e) { - throw Exception('Failed to check recovery status: $e'); - } - } - - /// Get recovery progress (how many vouches received vs threshold) - Future> getRecoveryProgress(String lostAccountAddress, String rescuerAddress) async { - try { - final activeRecovery = await getActiveRecovery(lostAccountAddress, rescuerAddress); - final config = await getRecoveryConfig(lostAccountAddress); - - if (activeRecovery == null || config == null) { - throw Exception('No active recovery or config found'); - } - - return { - 'vouches': activeRecovery.friends.length, - 'threshold': config.threshold, - 'delayPeriod': config.delayPeriod, - 'created': activeRecovery.created, - }; - } catch (e) { - throw Exception('Failed to get recovery progress: $e'); - } - } - - /// Get recovery constants - Future> getConstants() async { - try { - final quantusApi = Planck(_substrateService.provider!); - final constants = quantusApi.constant.recovery; - - return { - 'configDepositBase': constants.configDepositBase, - 'friendDepositFactor': constants.friendDepositFactor, - 'maxFriends': constants.maxFriends, - 'recoveryDeposit': constants.recoveryDeposit, - }; - } catch (e) { - throw Exception('Failed to get recovery constants: $e'); - } - } - - /// Helper to create a balance transfer call for recovered account - Balances createBalanceTransferCall(String recipientAddress, BigInt amount) { - final quantusApi = Planck(_substrateService.provider!); - final accountID = crypto.ss58ToAccountId(s: recipientAddress); - final dest = const multi_address.$MultiAddress().id(accountID); - final call = quantusApi.tx.balances.transferAllowDeath(dest: dest, value: amount); - return call; - } - - /// Convenience method to transfer balance as recovered account - Future transferAsRecovered({ - required Account rescuerAccount, - required String recoveredAccountAddress, - required String recipientAddress, - required BigInt amount, - }) async { - try { - final transferCall = createBalanceTransferCall(recipientAddress, amount); - return await callAsRecovered( - rescuerAccount: rescuerAccount, - recoveredAccountAddress: recoveredAccountAddress, - call: transferCall, - ); - } catch (e) { - throw Exception('Failed to transfer as recovered: $e'); - } - } -} diff --git a/quantus_sdk/lib/src/services/reversible_transfers_service.dart b/quantus_sdk/lib/src/services/reversible_transfers_service.dart index 96c8e1470..66921f264 100644 --- a/quantus_sdk/lib/src/services/reversible_transfers_service.dart +++ b/quantus_sdk/lib/src/services/reversible_transfers_service.dart @@ -257,22 +257,59 @@ class ReversibleTransfersService { quantusPrint('getInterceptedAccounts: $guardianAddress'); try { - final quantusApi = Planck(_substrateService.provider!); - final accountId = crypto.ss58ToAccountId(s: guardianAddress); - final interceptedAccounts = await quantusApi.query.reversibleTransfers.guardianIndex(accountId); - - List result = interceptedAccounts.map((id) { - final address = AddressExtension.ss58AddressFromBytes(Uint8List.fromList(id)); + final provider = _substrateService.provider!; + final quantusApi = Planck(provider); + final guardian = crypto.ss58ToAccountId(s: guardianAddress); + + // The runtime no longer keeps a guardian -> accounts reverse index, so walk + // the HighSecurityAccounts map and keep the entries naming this guardian. + final accountIds = await _highSecurityAccountIds(provider, quantusApi); + final configs = await quantusApi.query.reversibleTransfers.multiHighSecurityAccounts(accountIds); + + final result = []; + for (var i = 0; i < accountIds.length; i++) { + final config = configs[i]; + if (config == null || !_sameAccount(config.guardian, guardian)) continue; + final address = AddressExtension.ss58AddressFromBytes(Uint8List.fromList(accountIds[i])); quantusPrint('intercepted account: $address'); - return address; - }).toList(); - + result.add(address); + } return result; } catch (e) { throw Exception('Failed to get intercepted accounts: $e'); } } + /// Every key of the `HighSecurityAccounts` map, read one page at a time. + /// + /// The map is `Blake2_128Concat`, so each storage key ends with the unhashed + /// `AccountId32` it was built from. + Future>> _highSecurityAccountIds(Provider provider, Planck quantusApi) async { + const pageSize = 256; + final prefix = quantusApi.query.reversibleTransfers.highSecurityAccountsMapPrefix(); + final state = StateApi(provider); + + final ids = >[]; + Uint8List? startKey; + while (true) { + final keys = await state.getKeysPaged(key: prefix, count: pageSize, startKey: startKey); + if (keys.isEmpty) return ids; + for (final key in keys) { + ids.add(key.sublist(key.length - 32)); + } + if (keys.length < pageSize) return ids; + startKey = keys.last; + } + } + + bool _sameAccount(List a, List b) { + if (a.length != b.length) return false; + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) return false; + } + return true; + } + Future getHighSecuritySetupFee( Account account, String guardianAccountId, diff --git a/quantus_sdk/test/chain/call_decoder_test.dart b/quantus_sdk/test/chain/call_decoder_test.dart index 934fd9d74..33fbf5791 100644 --- a/quantus_sdk/test/chain/call_decoder_test.dart +++ b/quantus_sdk/test/chain/call_decoder_test.dart @@ -5,7 +5,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:quantus_sdk/generated/planck/pallets/balances.dart' as balances_pallet; import 'package:quantus_sdk/generated/planck/pallets/multisig.dart' as multisig_pallet; import 'package:quantus_sdk/generated/planck/pallets/preimage.dart' as preimage_pallet; -import 'package:quantus_sdk/generated/planck/pallets/recovery.dart' as recovery_pallet; import 'package:quantus_sdk/generated/planck/pallets/reversible_transfers.dart' as reversible_pallet; import 'package:quantus_sdk/generated/planck/pallets/system.dart' as system_pallet; import 'package:quantus_sdk/generated/planck/pallets/tech_collective.dart' as collective_pallet; @@ -151,15 +150,11 @@ void main() { expect(valueField(decoded, 'Threshold').value, '2 of 2'); }); - test('execute and cancel flag that the proposal contents are not in the payload', () { - for (final decoded in [ - roundTrip(const multisig_pallet.Txs().execute(multisigAddress: aliceId, proposalId: 4)), - roundTrip(const multisig_pallet.Txs().cancel(multisigAddress: aliceId, proposalId: 4)), - ]) { - final field = valueField(decoded, 'Proposal id'); - expect(field.value, '4'); - expect(field.note, contains('not part of what you sign')); - } + test('cancel flags that the proposal contents are not in the payload', () { + final decoded = roundTrip(const multisig_pallet.Txs().cancel(multisigAddress: aliceId, proposalId: 4)); + final field = valueField(decoded, 'Proposal id'); + expect(field.value, '4'); + expect(field.note, contains('not part of what you sign')); }); test('claim_deposits decodes with only the multisig account', () { @@ -262,19 +257,6 @@ void main() { expect(nestedField(decoded, 'Call 1').call.call, 'transfer_allow_death'); expect(nestedField(decoded, 'Call 2').call.call, 'vote'); }); - - test('recovery.as_recovered lifts the wrapped transfer summary', () { - final decoded = roundTrip( - const recovery_pallet.Txs().asRecovered( - account: dest(aliceId), - call: const balances_pallet.Txs().transferAllowDeath(dest: dest(bobId), value: oneToken), - ), - ); - - expect(decoded.call, 'as_recovered'); - expect(nestedField(decoded, 'Call').call.call, 'transfer_allow_death'); - expect(decoded.summary?.amount, oneToken); - }); }); group('strictness and fallback', () { diff --git a/quantus_sdk/test/multisig_service_test.dart b/quantus_sdk/test/multisig_service_test.dart index 723b975c1..131c48e0d 100644 --- a/quantus_sdk/test/multisig_service_test.dart +++ b/quantus_sdk/test/multisig_service_test.dart @@ -3,7 +3,7 @@ import 'dart:typed_data'; import 'package:flutter_test/flutter_test.dart'; import 'package:polkadart/scale_codec.dart'; import 'package:quantus_sdk/generated/planck/pallets/balances.dart' as balances_pallet; -import 'package:quantus_sdk/generated/planck/types/pallet_multisig/pallet/call.dart' show Approve; +import 'package:quantus_sdk/generated/planck/types/pallet_multisig/pallet/call.dart' show Approve, Execute; import 'package:quantus_sdk/generated/planck/types/quantus_runtime/runtime_call.dart'; import 'package:quantus_sdk/generated/planck/types/sp_runtime/multiaddress/multi_address.dart'; import 'package:quantus_sdk/src/chain/call_decoder.dart'; @@ -520,10 +520,71 @@ void main() { }); group('MultisigService.buildExecuteCall', () { + // Execute resubmits the proposal's inner call, and the runtime dispatches it + // only when it re-encodes to the stored bytes. + final innerCall = const balances_pallet.Txs().transferAllowDeath( + dest: MultiAddress.values.id(Uint8List.fromList(List.filled(32, 0xCC))), + value: BigInt.from(750000000000), + ); + test('returns a Multisig runtime call for valid params', () { - final call = MultisigService().buildExecuteCall(msig: _buildTestMsig(), proposalId: 3); + final call = MultisigService().buildExecuteCall(msig: _buildTestMsig(), proposalId: 3, call: innerCall.encode()); expect(call.encode().isNotEmpty, isTrue); }); + + test('re-encodes the inner call to the exact stored bytes', () { + final innerBytes = innerCall.encode(); + final execute = MultisigService().buildExecuteCall(msig: _buildTestMsig(), proposalId: 7, call: innerBytes); + + final decoded = RuntimeCall.codec.decode(Input.fromBytes(execute.encode())); + final executeCall = (decoded as Multisig).value0 as Execute; + + expect(executeCall.proposalId, 7); + expect(executeCall.call.encode(), innerBytes); + }); + + test('carries the inner call inline, with no length prefix', () { + // `approve` length-prefixes its `BoundedVec`; `execute` takes a + // `Box` and must not. + final innerBytes = innerCall.encode(); + final msig = _buildTestMsig(); + final execute = MultisigService().buildExecuteCall(msig: msig, proposalId: 7, call: innerBytes); + final approve = MultisigService().buildApproveCall(msig: msig, proposalId: 7, call: innerBytes); + + expect(execute.encode().length, approve.encode().length - _compactLength(innerBytes.length)); + }); + + test('rejects a call larger than a signer will review', () { + // The limit is sized for a batch_all of 32 transfers (1707 bytes inside a + // multisig wrapper), well above anything the wallet itself builds. + final oversized = List.filled(CallDecoder.maxCallBytes + 1, 0); + expect( + () => MultisigService().buildExecuteCall(msig: _buildTestMsig(), proposalId: 7, call: oversized), + throwsA(isA()), + ); + expect( + () => MultisigService().buildApproveCall(msig: _buildTestMsig(), proposalId: 7, call: oversized), + throwsA(isA()), + ); + }); + + test('rejects call bytes that do not decode', () { + expect( + () => MultisigService().buildExecuteCall(msig: _buildTestMsig(), proposalId: 7, call: [0xff, 0xff]), + throwsA(anything), + ); + }); + + test('rejects trailing bytes after the inner call', () { + expect( + () => MultisigService().buildExecuteCall( + msig: _buildTestMsig(), + proposalId: 7, + call: [...innerCall.encode(), 0x00], + ), + throwsA(isA()), + ); + }); }); group('MultisigService.buildCancelCall', () { @@ -618,3 +679,11 @@ MultisigAccount _buildTestMsig() { myMemberAccountId: signerB, ); } + +/// Byte length of the SCALE compact encoding of [value]. +int _compactLength(int value) { + if (value < 64) return 1; + if (value < 16384) return 2; + if (value < 1073741824) return 4; + return 5; +}