From 182ba59a09f9687f2e5af9a3f77d1eaef628eb0d Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 01:20:16 +0800 Subject: [PATCH 1/4] feat(multisig): carry the proposal's inner call on execute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regenerates the polkadart bindings against the runtime from chain PR #675 and threads the proposal's stored call through `multisig.execute`, so the executor signs the call that dispatches instead of an opaque proposal id — in both the in-app and the hardware (Keystone) flow. Unlike `approve`, execute takes a `Box`: inline, no length prefix. `CallDecoder.decodeRuntimeCall` decodes the stored bytes back into the call, so a proposal the bundled metadata cannot decode fails before signing rather than producing a call the chain rejects. The regenerated metadata also trims the runtime surface, which the clients have to follow: - pallet-recovery is gone. `RecoveryService` and the recovery describer go with it; nothing in the apps called them. - Balances `force_*` and `upgrade_accounts`, Treasury `set_treasury_portion` and every Utility call but `batch_all` are gone, along with their describers. - `ReversibleTransfers::GuardianIndex` is gone. `getInterceptedAccounts` now walks the `HighSecurityAccounts` map and keeps the entries naming the guardian, preserving the entrusted-accounts feature. - The cold wallet's `force_transfer` debug payload is dropped; the display case it covered (funds leaving an account that is not the signer) is now exercised through a multisig proposal. Tests: execute round-trips the stored bytes, encodes inline (asserted against approve's length-prefixed encoding), and rejects undecodable or trailing bytes; `requireCallBytes` guards both resubmitting actions. --- cold-wallet-app/lib/debug/debug_payloads.dart | 17 - cold-wallet-app/test/call_display_test.dart | 4 +- .../transaction_submission_service.dart | 11 +- .../multisig_action_confirm_sheet.dart | 4 + .../multisig_approve_confirm_sheet.dart | 2 +- .../multisig_execute_confirm_sheet.dart | 13 +- .../multisig_require_call_bytes_test.dart | 25 + .../generated/planck/pallets/balances.dart | 46 -- .../generated/planck/pallets/multisig.dart | 32 +- .../generated/planck/pallets/recovery.dart | 338 --------- .../planck/pallets/reversible_transfers.dart | 163 +++-- .../lib/generated/planck/pallets/system.dart | 16 +- .../planck/pallets/treasury_pallet.dart | 49 +- .../lib/generated/planck/pallets/utility.dart | 117 +--- .../lib/generated/planck/pallets/vesting.dart | 24 +- .../lib/generated/planck/pallets/zk_tree.dart | 27 + quantus_sdk/lib/generated/planck/planck.dart | 56 +- .../types/pallet_balances/pallet/call.dart | 293 -------- .../types/pallet_balances/pallet/error.dart | 12 +- .../types/pallet_balances/pallet/event.dart | 73 +- .../types/adjustment_direction.dart | 49 -- .../pallet_mining_rewards/pallet/event.dart | 119 +--- .../types/pallet_multisig/pallet/call.dart | 64 +- .../types/pallet_multisig/pallet/error.dart | 7 +- .../pallet_recovery/active_recovery.dart | 76 -- .../types/pallet_recovery/deposit_kind.dart | 135 ---- .../types/pallet_recovery/pallet/call.dart | 653 ------------------ .../types/pallet_recovery/pallet/error.dart | 128 ---- .../types/pallet_recovery/pallet/event.dart | 477 ------------- .../pallet_recovery/recovery_config.dart | 89 --- .../pallet/call.dart | 24 + .../pallet/error.dart | 11 +- .../types/pallet_treasury/pallet/call.dart | 54 +- .../types/pallet_treasury/pallet/error.dart | 6 +- .../types/pallet_treasury/pallet/event.dart | 57 +- .../types/pallet_utility/pallet/call.dart | 438 +----------- .../types/pallet_utility/pallet/event.dart | 362 +--------- .../types/pallet_vesting/pallet/call.dart | 24 +- .../types/pallet_vesting/pallet/error.dart | 19 +- .../types/pallet_vesting/pallet/event.dart | 31 +- .../types/pallet_wormhole/pallet/error.dart | 6 +- .../types/pallet_zk_tree/pallet/error.dart | 8 +- .../types/pallet_zk_tree/pallet/event.dart | 42 +- .../types/quantus_runtime/runtime_call.dart | 86 +-- .../types/quantus_runtime/runtime_event.dart | 97 +-- quantus_sdk/lib/quantus_sdk.dart | 1 - quantus_sdk/lib/src/chain/call_decoder.dart | 158 +---- .../lib/src/services/multisig_service.dart | 24 +- .../lib/src/services/recovery_service.dart | 310 --------- .../reversible_transfers_service.dart | 55 +- quantus_sdk/test/chain/call_decoder_test.dart | 28 +- quantus_sdk/test/multisig_service_test.dart | 59 +- 52 files changed, 650 insertions(+), 4369 deletions(-) create mode 100644 mobile-app/test/unit/multisig_require_call_bytes_test.dart delete mode 100644 quantus_sdk/lib/generated/planck/pallets/recovery.dart delete mode 100644 quantus_sdk/lib/generated/planck/types/pallet_balances/types/adjustment_direction.dart delete mode 100644 quantus_sdk/lib/generated/planck/types/pallet_recovery/active_recovery.dart delete mode 100644 quantus_sdk/lib/generated/planck/types/pallet_recovery/deposit_kind.dart delete mode 100644 quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/call.dart delete mode 100644 quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/error.dart delete mode 100644 quantus_sdk/lib/generated/planck/types/pallet_recovery/pallet/event.dart delete mode 100644 quantus_sdk/lib/generated/planck/types/pallet_recovery/recovery_config.dart delete mode 100644 quantus_sdk/lib/src/services/recovery_service.dart 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..59946e7a8 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; @@ -48,14 +47,18 @@ class CallDecoder { /// /// 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 +72,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 +95,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 +378,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 +387,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 +405,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 +522,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/services/multisig_service.dart b/quantus_sdk/lib/src/services/multisig_service.dart index 97d1eaf13..6b711135f 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'; @@ -449,17 +450,30 @@ 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}) { + 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 +483,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..d9851a68a 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,57 @@ 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 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 +665,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; +} From acfe845c0c94ee5b744d39704d85bea6145a81ee Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 09:01:18 +0800 Subject: [PATCH 2/4] feat(multisig): cap the call a proposal may carry at 2 KiB A call a signer cannot review is one they cannot meaningfully approve, so bound what propose, approve and execute will build. Sized by the largest call we ever expect to put through a multisig: a `batch_all` of 32 transfers (double the 16 a batch is expected to carry). At the worst-case encoding of every field that is 1667 bytes, or 1707 inside a multisig wrapper, so 2 KiB leaves headroom. The chain's own `MaxCallSize` is 10 KiB; this is deliberately tighter. The limit sits on the multisig builders, not on `CallDecoder.decodeRuntimeCall`: `system.set_code` and `preimage.note_preimage` legitimately carry a runtime blob, and the chain's 10 KiB proposal bound already keeps them out of a multisig. --- quantus_sdk/lib/src/chain/call_decoder.dart | 21 +++++++++++++++++++ .../lib/src/services/multisig_service.dart | 3 +++ quantus_sdk/test/multisig_service_test.dart | 14 +++++++++++++ 3 files changed, 38 insertions(+) diff --git a/quantus_sdk/lib/src/chain/call_decoder.dart b/quantus_sdk/lib/src/chain/call_decoder.dart index 59946e7a8..0ee229138 100644 --- a/quantus_sdk/lib/src/chain/call_decoder.dart +++ b/quantus_sdk/lib/src/chain/call_decoder.dart @@ -43,6 +43,27 @@ import 'package:quantus_sdk/src/services/datetime_formatting_service.dart'; class CallDecoder { const CallDecoder._(); + /// Largest encoded call a multisig proposal may carry. + /// + /// Sized by the biggest call we ever expect to put through a multisig: a + /// `batch_all` of 32 transfers — double the 16 a batch is expected to carry — + /// which is 1667 bytes at the worst-case encoding of every field, or 1707 + /// inside a multisig wrapper. The chain's own `MaxCallSize` is 10 KiB; this is + /// deliberately tighter, because a call a signer cannot review is one they + /// cannot meaningfully approve. + /// + /// This bounds the multisig paths only. `system.set_code` and + /// `preimage.note_preimage` legitimately carry a runtime blob and are governed + /// by their own limits. + static const int maxCallBytes = 2 * 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 diff --git a/quantus_sdk/lib/src/services/multisig_service.dart b/quantus_sdk/lib/src/services/multisig_service.dart index 6b711135f..7cc591ba7 100644 --- a/quantus_sdk/lib/src/services/multisig_service.dart +++ b/quantus_sdk/lib/src/services/multisig_service.dart @@ -375,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); } @@ -418,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); } @@ -456,6 +458,7 @@ class MultisigService { /// 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, diff --git a/quantus_sdk/test/multisig_service_test.dart b/quantus_sdk/test/multisig_service_test.dart index d9851a68a..131c48e0d 100644 --- a/quantus_sdk/test/multisig_service_test.dart +++ b/quantus_sdk/test/multisig_service_test.dart @@ -554,6 +554,20 @@ void main() { 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]), From 5fbe0aa664bfbfb178b01ee5acbe6fcd9abfb128 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 18:59:20 +0800 Subject: [PATCH 3/4] refactor(multisig): mirror the chain's MaxCallSize instead of a tighter limit A client limit below the chain's refuses proposals the chain accepts, leaving a multisig no cold signer can act on. Use the chain's number: 10 KiB, from `pallet_multisig::Config::MaxCallSize`. --- quantus_sdk/lib/src/chain/call_decoder.dart | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/quantus_sdk/lib/src/chain/call_decoder.dart b/quantus_sdk/lib/src/chain/call_decoder.dart index 0ee229138..c45f3a3c5 100644 --- a/quantus_sdk/lib/src/chain/call_decoder.dart +++ b/quantus_sdk/lib/src/chain/call_decoder.dart @@ -43,19 +43,13 @@ import 'package:quantus_sdk/src/services/datetime_formatting_service.dart'; class CallDecoder { const CallDecoder._(); - /// Largest encoded call a multisig proposal may carry. + /// Largest inner call a multisig proposal may carry, mirroring the runtime's + /// `pallet_multisig::Config::MaxCallSize` (`BoundedVec`, 10 KiB). /// - /// Sized by the biggest call we ever expect to put through a multisig: a - /// `batch_all` of 32 transfers — double the 16 a batch is expected to carry — - /// which is 1667 bytes at the worst-case encoding of every field, or 1707 - /// inside a multisig wrapper. The chain's own `MaxCallSize` is 10 KiB; this is - /// deliberately tighter, because a call a signer cannot review is one they - /// cannot meaningfully approve. - /// - /// This bounds the multisig paths only. `system.set_code` and - /// `preimage.note_preimage` legitimately carry a runtime blob and are governed - /// by their own limits. - static const int maxCallBytes = 2 * 1024; + /// 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) { From a3e6d215079a4093dfc86ad646a6e11141209a26 Mon Sep 17 00:00:00 2001 From: Nikolaus Heger Date: Sun, 30 Aug 2026 19:57:44 +0800 Subject: [PATCH 4/4] fix(sdk): point the bundled version constants at the regenerated metadata The polkadart bindings were regenerated against spec 147 / tx 6, but `bundledSpecVersion` and `bundledTransactionVersion` still said 136 / 3. That made `ParsedPayload.specMatchesBundled` false for every real payload, so the cold wallet would have warned that the call may have been decoded against shifted indices when nothing was wrong. Also raises the Dart parser's payload cap to 12 KiB, matching the firmware and the reference parser, so a payload one accepts is not rejected by another. --- quantus_sdk/lib/src/constants/app_constants.dart | 4 ++-- quantus_sdk/lib/src/quantus_payload_parser.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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.