diff --git a/packages/types/src/interfaces/augment-types.ts b/packages/types/src/interfaces/augment-types.ts index 090019e3..03f2d308 100644 --- a/packages/types/src/interfaces/augment-types.ts +++ b/packages/types/src/interfaces/augment-types.ts @@ -10,8 +10,10 @@ import type { BusinessData, BusinessIdentifier, OfferingData, OfferingIdentifier import type { Assignment, AssignmentCount, AssignmentParams, Attestation, AttestationIndexType, CeremonyIndexType, CeremonyPhaseType, ClaimOfAttendance, ClaimOfAttendanceSigningPayload, CommunityCeremonyStats, CommunityReputation, Meetup, MeetupAssignment, MeetupIndexType, MeetupResult, MeetupTimeOffsetType, ParticipantIndexType, ParticipantRegistration, ProofOfAttendance, RegistrationType, Reputation } from '@encointer/types/interfaces/ceremony'; import type { FixedI64F64, IpfsCid, PalletString } from '@encointer/types/interfaces/common'; import type { AnnouncementSigner, Bip340, CidDigest, CidName, CommunityCeremony, CommunityIdentifier, CommunityMetadataType, CommunityRules, DegreeFixed, DegreeRpc, GeoHash, Location, LocationRpc, NominalIncomeType } from '@encointer/types/interfaces/community'; +import type { EncointerBalanceTransferArgs, EncointerGetter, EncointerGetterArgs, EncointerPublicGetter, EncointerTrustedCall, EncointerTrustedCallSigned, EncointerTrustedGetter, EncointerTrustedGetterSigned, GrantReputationArgs, RegisterAttestationsArgs, RegisterParticipantArgs } from '@encointer/types/interfaces/encointerWorker'; +import type { BalanceSetBalanceArgs, BalanceShieldArgs, BalanceTransferArgs, BalanceUnshieldArgs, IntegriteeGetter, IntegriteePublicGetter, IntegriteeTrustedCall, IntegriteeTrustedCallSigned, IntegriteeTrustedGetter, IntegriteeTrustedGetterSigned, IntegriteeTrustedOperation, TimestampSetArgs } from '@encointer/types/interfaces/integriteeWorker'; import type { SchedulerState, SystemNumber } from '@encointer/types/interfaces/scheduler'; -import type { BalanceTransferArgs, ClientRequest, Enclave, Getter, GetterArgs, GrantReputationArgs, PublicGetter, RegisterAttestationsArgs, RegisterParticipantArgs, Request, ShardIdentifier, TrustedCall, TrustedCallSigned, TrustedGetter, TrustedGetterSigned, WorkerEncoded } from '@encointer/types/interfaces/worker'; +import type { DirectRequestStatus, Enclave, GetterArgs, ParentchainId, Request, RpcReturnValue, ShardIdentifier, TrustedOperationStatus, Vault, WorkerEncoded } from '@encointer/types/interfaces/worker'; import type { Data, StorageKey } from '@polkadot/types'; import type { BitVec, Bool, Bytes, F32, F64, I128, I16, I256, I32, I64, I8, ISize, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, f32, f64, i128, i16, i256, i32, i64, i8, isize, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec'; import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets'; @@ -158,8 +160,11 @@ declare module '@polkadot/types/types/registry' { Balance: Balance; BalanceEntry: BalanceEntry; BalanceOf: BalanceOf; + BalanceSetBalanceArgs: BalanceSetBalanceArgs; + BalanceShieldArgs: BalanceShieldArgs; BalanceTransferArgs: BalanceTransferArgs; BalanceType: BalanceType; + BalanceUnshieldArgs: BalanceUnshieldArgs; BeefyAuthoritySet: BeefyAuthoritySet; BeefyCommitment: BeefyCommitment; BeefyEquivocationProof: BeefyEquivocationProof; @@ -242,7 +247,6 @@ declare module '@polkadot/types/types/registry' { ClassDetails: ClassDetails; ClassId: ClassId; ClassMetadata: ClassMetadata; - ClientRequest: ClientRequest; CodecHash: CodecHash; CodeHash: CodeHash; CodeSource: CodeSource; @@ -367,6 +371,7 @@ declare module '@polkadot/types/types/registry' { Digest: Digest; DigestItem: DigestItem; DigestOf: DigestOf; + DirectRequestStatus: DirectRequestStatus; DispatchClass: DispatchClass; DispatchError: DispatchError; DispatchErrorModule: DispatchErrorModule; @@ -406,6 +411,14 @@ declare module '@polkadot/types/types/registry' { Enclave: Enclave; EncodedFinalityProofs: EncodedFinalityProofs; EncodedJustification: EncodedJustification; + EncointerBalanceTransferArgs: EncointerBalanceTransferArgs; + EncointerGetter: EncointerGetter; + EncointerGetterArgs: EncointerGetterArgs; + EncointerPublicGetter: EncointerPublicGetter; + EncointerTrustedCall: EncointerTrustedCall; + EncointerTrustedCallSigned: EncointerTrustedCallSigned; + EncointerTrustedGetter: EncointerTrustedGetter; + EncointerTrustedGetterSigned: EncointerTrustedGetterSigned; Epoch: Epoch; EpochAuthorship: EpochAuthorship; Era: Era; @@ -542,7 +555,6 @@ declare module '@polkadot/types/types/registry' { FungiblesAccessError: FungiblesAccessError; Gas: Gas; GeoHash: GeoHash; - Getter: Getter; GetterArgs: GetterArgs; GiltBid: GiltBid; GlobalValidationData: GlobalValidationData; @@ -628,6 +640,13 @@ declare module '@polkadot/types/types/registry' { InstantiateReturnValueTo267: InstantiateReturnValueTo267; InstructionV2: InstructionV2; InstructionWeights: InstructionWeights; + IntegriteeGetter: IntegriteeGetter; + IntegriteePublicGetter: IntegriteePublicGetter; + IntegriteeTrustedCall: IntegriteeTrustedCall; + IntegriteeTrustedCallSigned: IntegriteeTrustedCallSigned; + IntegriteeTrustedGetter: IntegriteeTrustedGetter; + IntegriteeTrustedGetterSigned: IntegriteeTrustedGetterSigned; + IntegriteeTrustedOperation: IntegriteeTrustedOperation; InteriorMultiLocation: InteriorMultiLocation; InvalidDisputeStatementKind: InvalidDisputeStatementKind; InvalidTransaction: InvalidTransaction; @@ -830,6 +849,7 @@ declare module '@polkadot/types/types/registry' { ParathreadClaimQueue: ParathreadClaimQueue; ParathreadEntry: ParathreadEntry; ParaValidatorIndex: ParaValidatorIndex; + ParentchainId: ParentchainId; ParticipantIndexType: ParticipantIndexType; ParticipantRegistration: ParticipantRegistration; Pays: Pays; @@ -876,7 +896,6 @@ declare module '@polkadot/types/types/registry' { ProxyDefinition: ProxyDefinition; ProxyState: ProxyState; ProxyType: ProxyType; - PublicGetter: PublicGetter; PvfCheckStatement: PvfCheckStatement; PvfExecTimeoutKind: PvfExecTimeoutKind; PvfPrepTimeoutKind: PvfPrepTimeoutKind; @@ -947,6 +966,7 @@ declare module '@polkadot/types/types/registry' { RoundSnapshot: RoundSnapshot; RoundState: RoundState; RpcMethods: RpcMethods; + RpcReturnValue: RpcReturnValue; RuntimeApiMetadataLatest: RuntimeApiMetadataLatest; RuntimeApiMetadataV15: RuntimeApiMetadataV15; RuntimeApiMethodMetadataV15: RuntimeApiMethodMetadataV15; @@ -1132,6 +1152,7 @@ declare module '@polkadot/types/types/registry' { TAssetDepositBalance: TAssetDepositBalance; Text: Text; Timepoint: Timepoint; + TimestampSetArgs: TimestampSetArgs; TokenError: TokenError; TombstoneContractInfo: TombstoneContractInfo; TraceBlockResponse: TraceBlockResponse; @@ -1152,10 +1173,7 @@ declare module '@polkadot/types/types/registry' { TreasuryProposal: TreasuryProposal; TrieId: TrieId; TrieIndex: TrieIndex; - TrustedCall: TrustedCall; - TrustedCallSigned: TrustedCallSigned; - TrustedGetter: TrustedGetter; - TrustedGetterSigned: TrustedGetterSigned; + TrustedOperationStatus: TrustedOperationStatus; Type: Type; u128: u128; U128: U128; @@ -1203,6 +1221,7 @@ declare module '@polkadot/types/types/registry' { ValidDisputeStatementKind: ValidDisputeStatementKind; ValidityAttestation: ValidityAttestation; ValidTransaction: ValidTransaction; + Vault: Vault; VecInboundHrmpMessage: VecInboundHrmpMessage; VersionedMultiAsset: VersionedMultiAsset; VersionedMultiAssets: VersionedMultiAssets; diff --git a/packages/types/src/interfaces/definitions.ts b/packages/types/src/interfaces/definitions.ts index 36e0e16a..c4f166d2 100644 --- a/packages/types/src/interfaces/definitions.ts +++ b/packages/types/src/interfaces/definitions.ts @@ -5,3 +5,5 @@ export { default as ceremony } from './ceremony/definitions.js'; export { default as community } from './community/definitions.js'; export { default as scheduler } from './scheduler/definitions.js'; export { default as worker } from './worker/definitions.js'; +export { default as encointerWorker } from './encointerWorker/definitions.js' +export { default as integriteeWorker } from './integriteeWorker/definitions.js' diff --git a/packages/types/src/interfaces/encointerWorker/definitions.ts b/packages/types/src/interfaces/encointerWorker/definitions.ts new file mode 100644 index 00000000..091d18b2 --- /dev/null +++ b/packages/types/src/interfaces/encointerWorker/definitions.ts @@ -0,0 +1,53 @@ +export default { + rpc: {}, + types: { + EncointerGetterArgs: '(AccountId, CommunityIdentifier)', + EncointerPublicGetter: { + _enum: { + total_issuance: 'CommunityIdentifier', + participant_count: 'CommunityIdentifier', + meetup_count: 'CommunityIdentifier', + ceremony_reward: 'CommunityIdentifier', + location_tolerance: 'CommunityIdentifier', + time_tolerance: 'CommunityIdentifier', + scheduler_state: 'CommunityIdentifier' + } + }, + EncointerTrustedGetter: { + _enum: { + balance: '(AccountId, CommunityIdentifier)', + participant_index: '(AccountId, CommunityIdentifier)', + meetup_index: '(AccountId, CommunityIdentifier)', + attestations: '(AccountId, CommunityIdentifier)', + meetup_registry: '(AccountId, CommunityIdentifier)' + } + }, + EncointerTrustedGetterSigned: { + getter: 'EncointerTrustedGetter', + signature: 'Signature' + }, + EncointerGetter: { + _enum: { + public: 'EncointerPublicGetter', + trusted: 'EncointerTrustedGetterSigned' + } + }, + EncointerTrustedCallSigned: { + call: 'EncointerTrustedCall', + nonce: 'u32', + signature: 'Signature' + }, + EncointerTrustedCall: { + _enum: { + balance_transfer: 'EncointerBalanceTransferArgs', + ceremonies_register_participant: 'RegisterParticipantArgs', + ceremonies_register_attestations: 'RegisterAttestationsArgs', + ceremonies_grant_reputation: 'GrantReputationArgs' + } + }, + EncointerBalanceTransferArgs: '(AccountId, AccountId, CommunityIdentifier, BalanceType)', + RegisterParticipantArgs: '(AccountId, CommunityIdentifier, Option>)', + RegisterAttestationsArgs: '(AccountId, Vec>)', + GrantReputationArgs: '(AccountId, CommunityIdentifier, AccountId)' + } +} diff --git a/packages/types/src/interfaces/encointerWorker/index.ts b/packages/types/src/interfaces/encointerWorker/index.ts new file mode 100644 index 00000000..7f1de782 --- /dev/null +++ b/packages/types/src/interfaces/encointerWorker/index.ts @@ -0,0 +1,4 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +export * from './types.js'; diff --git a/packages/types/src/interfaces/encointerWorker/types.ts b/packages/types/src/interfaces/encointerWorker/types.ts new file mode 100644 index 00000000..2436ee89 --- /dev/null +++ b/packages/types/src/interfaces/encointerWorker/types.ts @@ -0,0 +1,96 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +import type { BalanceType } from '@encointer/types/interfaces/balances'; +import type { Attestation, ProofOfAttendance } from '@encointer/types/interfaces/ceremony'; +import type { CommunityIdentifier } from '@encointer/types/interfaces/community'; +import type { Enum, Option, Struct, Vec, u32 } from '@polkadot/types-codec'; +import type { ITuple } from '@polkadot/types-codec/types'; +import type { Signature } from '@polkadot/types/interfaces/extrinsics'; +import type { AccountId } from '@polkadot/types/interfaces/runtime'; + +/** @name EncointerBalanceTransferArgs */ +export interface EncointerBalanceTransferArgs extends ITuple<[AccountId, AccountId, CommunityIdentifier, BalanceType]> {} + +/** @name EncointerGetter */ +export interface EncointerGetter extends Enum { + readonly isPublic: boolean; + readonly asPublic: EncointerPublicGetter; + readonly isTrusted: boolean; + readonly asTrusted: EncointerTrustedGetterSigned; + readonly type: 'Public' | 'Trusted'; +} + +/** @name EncointerGetterArgs */ +export interface EncointerGetterArgs extends ITuple<[AccountId, CommunityIdentifier]> {} + +/** @name EncointerPublicGetter */ +export interface EncointerPublicGetter extends Enum { + readonly isTotalIssuance: boolean; + readonly asTotalIssuance: CommunityIdentifier; + readonly isParticipantCount: boolean; + readonly asParticipantCount: CommunityIdentifier; + readonly isMeetupCount: boolean; + readonly asMeetupCount: CommunityIdentifier; + readonly isCeremonyReward: boolean; + readonly asCeremonyReward: CommunityIdentifier; + readonly isLocationTolerance: boolean; + readonly asLocationTolerance: CommunityIdentifier; + readonly isTimeTolerance: boolean; + readonly asTimeTolerance: CommunityIdentifier; + readonly isSchedulerState: boolean; + readonly asSchedulerState: CommunityIdentifier; + readonly type: 'TotalIssuance' | 'ParticipantCount' | 'MeetupCount' | 'CeremonyReward' | 'LocationTolerance' | 'TimeTolerance' | 'SchedulerState'; +} + +/** @name EncointerTrustedCall */ +export interface EncointerTrustedCall extends Enum { + readonly isBalanceTransfer: boolean; + readonly asBalanceTransfer: EncointerBalanceTransferArgs; + readonly isCeremoniesRegisterParticipant: boolean; + readonly asCeremoniesRegisterParticipant: RegisterParticipantArgs; + readonly isCeremoniesRegisterAttestations: boolean; + readonly asCeremoniesRegisterAttestations: RegisterAttestationsArgs; + readonly isCeremoniesGrantReputation: boolean; + readonly asCeremoniesGrantReputation: GrantReputationArgs; + readonly type: 'BalanceTransfer' | 'CeremoniesRegisterParticipant' | 'CeremoniesRegisterAttestations' | 'CeremoniesGrantReputation'; +} + +/** @name EncointerTrustedCallSigned */ +export interface EncointerTrustedCallSigned extends Struct { + readonly call: EncointerTrustedCall; + readonly nonce: u32; + readonly signature: Signature; +} + +/** @name EncointerTrustedGetter */ +export interface EncointerTrustedGetter extends Enum { + readonly isBalance: boolean; + readonly asBalance: ITuple<[AccountId, CommunityIdentifier]>; + readonly isParticipantIndex: boolean; + readonly asParticipantIndex: ITuple<[AccountId, CommunityIdentifier]>; + readonly isMeetupIndex: boolean; + readonly asMeetupIndex: ITuple<[AccountId, CommunityIdentifier]>; + readonly isAttestations: boolean; + readonly asAttestations: ITuple<[AccountId, CommunityIdentifier]>; + readonly isMeetupRegistry: boolean; + readonly asMeetupRegistry: ITuple<[AccountId, CommunityIdentifier]>; + readonly type: 'Balance' | 'ParticipantIndex' | 'MeetupIndex' | 'Attestations' | 'MeetupRegistry'; +} + +/** @name EncointerTrustedGetterSigned */ +export interface EncointerTrustedGetterSigned extends Struct { + readonly getter: EncointerTrustedGetter; + readonly signature: Signature; +} + +/** @name GrantReputationArgs */ +export interface GrantReputationArgs extends ITuple<[AccountId, CommunityIdentifier, AccountId]> {} + +/** @name RegisterAttestationsArgs */ +export interface RegisterAttestationsArgs extends ITuple<[AccountId, Vec]> {} + +/** @name RegisterParticipantArgs */ +export interface RegisterParticipantArgs extends ITuple<[AccountId, CommunityIdentifier, Option]> {} + +export type PHANTOM_ENCOINTERWORKER = 'encointerWorker'; diff --git a/packages/types/src/interfaces/integriteeWorker/definitions.ts b/packages/types/src/interfaces/integriteeWorker/definitions.ts new file mode 100644 index 00000000..bd324299 --- /dev/null +++ b/packages/types/src/interfaces/integriteeWorker/definitions.ts @@ -0,0 +1,60 @@ +export default { + rpc: {}, + types: { + IntegriteePublicGetter: { + _enum: { + total_issuance: 'CommunityIdentifier', + participant_count: 'CommunityIdentifier', + meetup_count: 'CommunityIdentifier', + ceremony_reward: 'CommunityIdentifier', + location_tolerance: 'CommunityIdentifier', + time_tolerance: 'CommunityIdentifier', + scheduler_state: 'CommunityIdentifier' + } + }, + IntegriteeTrustedGetter: { + _enum: { + free_balance: 'AccountId', + reserved_balance: 'AccountId', + nonce: 'AccountId', + } + }, + IntegriteeTrustedGetterSigned: { + getter: 'IntegriteeTrustedGetter', + signature: 'MultiSignature' + }, + IntegriteeGetter: { + _enum: { + public: 'IntegriteePublicGetter', + trusted: 'IntegriteeTrustedGetterSigned' + } + }, + IntegriteeTrustedOperation: { + _enum: { + indirect_call: 'IntegriteeTrustedCallSigned', + direct_call: 'IntegriteeTrustedCallSigned', + get: 'IntegriteeGetter' + } + }, + IntegriteeTrustedCallSigned: { + call: 'IntegriteeTrustedCall', + nonce: 'u32', + signature: 'MultiSignature' + }, + IntegriteeTrustedCall: { + _enum: { + noop: 'AccountId', + balance_set_balance: 'BalanceSetBalanceArgs', + balance_transfer: 'BalanceTransferArgs', + balance_unshield: 'BalanceUnshieldArgs', + balance_shield: 'BalanceShieldArgs', + timestamp_set: 'TimestampSetArgs', + } + }, + BalanceSetBalanceArgs: '(AccountId, AccountId, BalanceType, BalanceType)', + BalanceTransferArgs: '(AccountId, AccountId, BalanceType)', + BalanceUnshieldArgs: '(AccountId, AccountId, BalanceType, ShardIdentifier)', + BalanceShieldArgs: '(AccountId, AccountId, BalanceType, ParentchainId)', + TimestampSetArgs: '(AccountId, H160, BalanceType)', + } +} diff --git a/packages/types/src/interfaces/integriteeWorker/index.ts b/packages/types/src/interfaces/integriteeWorker/index.ts new file mode 100644 index 00000000..7f1de782 --- /dev/null +++ b/packages/types/src/interfaces/integriteeWorker/index.ts @@ -0,0 +1,4 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +export * from './types.js'; diff --git a/packages/types/src/interfaces/integriteeWorker/types.ts b/packages/types/src/interfaces/integriteeWorker/types.ts new file mode 100644 index 00000000..aa239de8 --- /dev/null +++ b/packages/types/src/interfaces/integriteeWorker/types.ts @@ -0,0 +1,107 @@ +// Auto-generated via `yarn polkadot-types-from-defs`, do not edit +/* eslint-disable */ + +import type { BalanceType } from '@encointer/types/interfaces/balances'; +import type { CommunityIdentifier } from '@encointer/types/interfaces/community'; +import type { ParentchainId, ShardIdentifier } from '@encointer/types/interfaces/worker'; +import type { Enum, Struct, u32 } from '@polkadot/types-codec'; +import type { ITuple } from '@polkadot/types-codec/types'; +import type { MultiSignature } from '@polkadot/types/interfaces/extrinsics'; +import type { AccountId, H160 } from '@polkadot/types/interfaces/runtime'; + +/** @name BalanceSetBalanceArgs */ +export interface BalanceSetBalanceArgs extends ITuple<[AccountId, AccountId, BalanceType, BalanceType]> {} + +/** @name BalanceShieldArgs */ +export interface BalanceShieldArgs extends ITuple<[AccountId, AccountId, BalanceType, ParentchainId]> {} + +/** @name BalanceTransferArgs */ +export interface BalanceTransferArgs extends ITuple<[AccountId, AccountId, BalanceType]> {} + +/** @name BalanceUnshieldArgs */ +export interface BalanceUnshieldArgs extends ITuple<[AccountId, AccountId, BalanceType, ShardIdentifier]> {} + +/** @name IntegriteeGetter */ +export interface IntegriteeGetter extends Enum { + readonly isPublic: boolean; + readonly asPublic: IntegriteePublicGetter; + readonly isTrusted: boolean; + readonly asTrusted: IntegriteeTrustedGetterSigned; + readonly type: 'Public' | 'Trusted'; +} + +/** @name IntegriteePublicGetter */ +export interface IntegriteePublicGetter extends Enum { + readonly isTotalIssuance: boolean; + readonly asTotalIssuance: CommunityIdentifier; + readonly isParticipantCount: boolean; + readonly asParticipantCount: CommunityIdentifier; + readonly isMeetupCount: boolean; + readonly asMeetupCount: CommunityIdentifier; + readonly isCeremonyReward: boolean; + readonly asCeremonyReward: CommunityIdentifier; + readonly isLocationTolerance: boolean; + readonly asLocationTolerance: CommunityIdentifier; + readonly isTimeTolerance: boolean; + readonly asTimeTolerance: CommunityIdentifier; + readonly isSchedulerState: boolean; + readonly asSchedulerState: CommunityIdentifier; + readonly type: 'TotalIssuance' | 'ParticipantCount' | 'MeetupCount' | 'CeremonyReward' | 'LocationTolerance' | 'TimeTolerance' | 'SchedulerState'; +} + +/** @name IntegriteeTrustedCall */ +export interface IntegriteeTrustedCall extends Enum { + readonly isNoop: boolean; + readonly asNoop: AccountId; + readonly isBalanceSetBalance: boolean; + readonly asBalanceSetBalance: BalanceSetBalanceArgs; + readonly isBalanceTransfer: boolean; + readonly asBalanceTransfer: BalanceTransferArgs; + readonly isBalanceUnshield: boolean; + readonly asBalanceUnshield: BalanceUnshieldArgs; + readonly isBalanceShield: boolean; + readonly asBalanceShield: BalanceShieldArgs; + readonly isTimestampSet: boolean; + readonly asTimestampSet: TimestampSetArgs; + readonly type: 'Noop' | 'BalanceSetBalance' | 'BalanceTransfer' | 'BalanceUnshield' | 'BalanceShield' | 'TimestampSet'; +} + +/** @name IntegriteeTrustedCallSigned */ +export interface IntegriteeTrustedCallSigned extends Struct { + readonly call: IntegriteeTrustedCall; + readonly nonce: u32; + readonly signature: MultiSignature; +} + +/** @name IntegriteeTrustedGetter */ +export interface IntegriteeTrustedGetter extends Enum { + readonly isFreeBalance: boolean; + readonly asFreeBalance: AccountId; + readonly isReservedBalance: boolean; + readonly asReservedBalance: AccountId; + readonly isNonce: boolean; + readonly asNonce: AccountId; + readonly type: 'FreeBalance' | 'ReservedBalance' | 'Nonce'; +} + +/** @name IntegriteeTrustedGetterSigned */ +export interface IntegriteeTrustedGetterSigned extends Struct { + readonly getter: IntegriteeTrustedGetter; + readonly signature: MultiSignature; +} + +/** @name IntegriteeTrustedOperation */ +export interface IntegriteeTrustedOperation extends Enum { + readonly isIndirectCall: boolean; + readonly asIndirectCall: IntegriteeTrustedCallSigned; + readonly isDirectCall: boolean; + readonly asDirectCall: IntegriteeTrustedCallSigned; + readonly isGet: boolean; + readonly asGet: IntegriteeGetter; + readonly type: 'IndirectCall' | 'DirectCall' | 'Get'; +} + +/** @name TimestampSetArgs */ +export interface TimestampSetArgs extends ITuple<[AccountId, H160, BalanceType]> {} + +export type PHANTOM_INTEGRITEEWORKER = 'integriteeWorker'; diff --git a/packages/types/src/interfaces/types.ts b/packages/types/src/interfaces/types.ts index d7f4cdf3..b8fe7d58 100644 --- a/packages/types/src/interfaces/types.ts +++ b/packages/types/src/interfaces/types.ts @@ -6,5 +6,7 @@ export * from './bazaar/types.js'; export * from './ceremony/types.js'; export * from './common/types.js'; export * from './community/types.js'; +export * from './encointerWorker/types.js'; +export * from './integriteeWorker/types.js'; export * from './scheduler/types.js'; export * from './worker/types.js'; diff --git a/packages/types/src/interfaces/worker/definitions.ts b/packages/types/src/interfaces/worker/definitions.ts index cc3c5e79..4be7303b 100644 --- a/packages/types/src/interfaces/worker/definitions.ts +++ b/packages/types/src/interfaces/worker/definitions.ts @@ -9,41 +9,31 @@ export default { timestamp: 'u64', url: 'Text' }, - PublicGetter: { - _enum: { - total_issuance: 'CommunityIdentifier', - participant_count: 'CommunityIdentifier', - meetup_count: 'CommunityIdentifier', - ceremony_reward: 'CommunityIdentifier', - location_tolerance: 'CommunityIdentifier', - time_tolerance: 'CommunityIdentifier', - scheduler_state: 'CommunityIdentifier' - } + RpcReturnValue: { + value: 'Vec', + do_watch: 'bool', + status: 'DirectRequestStatus' }, - TrustedGetter: { + DirectRequestStatus: { _enum: { - balance: '(AccountId, CommunityIdentifier)', - participant_index: '(AccountId, CommunityIdentifier)', - meetup_index: '(AccountId, CommunityIdentifier)', - attestations: '(AccountId, CommunityIdentifier)', - meetup_registry: '(AccountId, CommunityIdentifier)' + Ok: null, + TrustedOperationStatus: 'TrustedOperationStatus', + Error: null } }, - TrustedGetterSigned: { - getter: 'TrustedGetter', - signature: 'Signature' - }, - Getter: { + TrustedOperationStatus: { _enum: { - public: 'PublicGetter', - trusted: 'TrustedGetterSigned' - } - }, - ClientRequest: { - _enum: { - PubKeyWorker: null, - MuRaPortWorker: null, - StfState: '(Getter, ShardIdentifier)' + Submitted: null, + Future: null, + Ready: null, + BroadCast: null, + InSidechainBlock: 'Hash', + Retracted: null, + FinalityTimeout: null, + Finalized: null, + Usurped: null, + Dropped: null, + Invalid: null } }, WorkerEncoded: 'Vec', @@ -51,22 +41,13 @@ export default { shard: 'ShardIdentifier', cyphertext: 'WorkerEncoded' }, - TrustedCallSigned: { - call: 'TrustedCall', - nonce: 'u32', - signature: 'Signature' - }, - TrustedCall: { + Vault: '(AccountId, ParentchainId)', + ParentchainId: { _enum: { - balance_transfer: 'BalanceTransferArgs', - ceremonies_register_participant: 'RegisterParticipantArgs', - ceremonies_register_attestations: 'RegisterAttestationsArgs', - ceremonies_grant_reputation: 'GrantReputationArgs' + Integritee: null, + TargetA: null, + TargetB: null, } }, - BalanceTransferArgs: '(AccountId, AccountId, CommunityIdentifier, BalanceType)', - RegisterParticipantArgs: '(AccountId, CommunityIdentifier, Option>)', - RegisterAttestationsArgs: '(AccountId, Vec>)', - GrantReputationArgs: '(AccountId, CommunityIdentifier, AccountId)' } } diff --git a/packages/types/src/interfaces/worker/types.ts b/packages/types/src/interfaces/worker/types.ts index 532a6884..194f3aca 100644 --- a/packages/types/src/interfaces/worker/types.ts +++ b/packages/types/src/interfaces/worker/types.ts @@ -1,24 +1,18 @@ // Auto-generated via `yarn polkadot-types-from-defs`, do not edit /* eslint-disable */ -import type { BalanceType } from '@encointer/types/interfaces/balances'; -import type { Attestation, ProofOfAttendance } from '@encointer/types/interfaces/ceremony'; import type { CommunityIdentifier } from '@encointer/types/interfaces/community'; -import type { Bytes, Enum, Option, Struct, Text, Vec, u32, u64 } from '@polkadot/types-codec'; +import type { Bytes, Enum, Struct, Text, bool, u64 } from '@polkadot/types-codec'; import type { ITuple } from '@polkadot/types-codec/types'; -import type { Signature } from '@polkadot/types/interfaces/extrinsics'; import type { AccountId, Hash } from '@polkadot/types/interfaces/runtime'; -/** @name BalanceTransferArgs */ -export interface BalanceTransferArgs extends ITuple<[AccountId, AccountId, CommunityIdentifier, BalanceType]> {} - -/** @name ClientRequest */ -export interface ClientRequest extends Enum { - readonly isPubKeyWorker: boolean; - readonly isMuRaPortWorker: boolean; - readonly isStfState: boolean; - readonly asStfState: ITuple<[Getter, ShardIdentifier]>; - readonly type: 'PubKeyWorker' | 'MuRaPortWorker' | 'StfState'; +/** @name DirectRequestStatus */ +export interface DirectRequestStatus extends Enum { + readonly isOk: boolean; + readonly isTrustedOperationStatus: boolean; + readonly asTrustedOperationStatus: TrustedOperationStatus; + readonly isError: boolean; + readonly type: 'Ok' | 'TrustedOperationStatus' | 'Error'; } /** @name Enclave */ @@ -29,95 +23,52 @@ export interface Enclave extends Struct { readonly url: Text; } -/** @name Getter */ -export interface Getter extends Enum { - readonly isPublic: boolean; - readonly asPublic: PublicGetter; - readonly isTrusted: boolean; - readonly asTrusted: TrustedGetterSigned; - readonly type: 'Public' | 'Trusted'; -} - /** @name GetterArgs */ export interface GetterArgs extends ITuple<[AccountId, CommunityIdentifier]> {} -/** @name GrantReputationArgs */ -export interface GrantReputationArgs extends ITuple<[AccountId, CommunityIdentifier, AccountId]> {} - -/** @name PublicGetter */ -export interface PublicGetter extends Enum { - readonly isTotalIssuance: boolean; - readonly asTotalIssuance: CommunityIdentifier; - readonly isParticipantCount: boolean; - readonly asParticipantCount: CommunityIdentifier; - readonly isMeetupCount: boolean; - readonly asMeetupCount: CommunityIdentifier; - readonly isCeremonyReward: boolean; - readonly asCeremonyReward: CommunityIdentifier; - readonly isLocationTolerance: boolean; - readonly asLocationTolerance: CommunityIdentifier; - readonly isTimeTolerance: boolean; - readonly asTimeTolerance: CommunityIdentifier; - readonly isSchedulerState: boolean; - readonly asSchedulerState: CommunityIdentifier; - readonly type: 'TotalIssuance' | 'ParticipantCount' | 'MeetupCount' | 'CeremonyReward' | 'LocationTolerance' | 'TimeTolerance' | 'SchedulerState'; +/** @name ParentchainId */ +export interface ParentchainId extends Enum { + readonly isIntegritee: boolean; + readonly isTargetA: boolean; + readonly isTargetB: boolean; + readonly type: 'Integritee' | 'TargetA' | 'TargetB'; } -/** @name RegisterAttestationsArgs */ -export interface RegisterAttestationsArgs extends ITuple<[AccountId, Vec]> {} - -/** @name RegisterParticipantArgs */ -export interface RegisterParticipantArgs extends ITuple<[AccountId, CommunityIdentifier, Option]> {} - /** @name Request */ export interface Request extends Struct { readonly shard: ShardIdentifier; readonly cyphertext: WorkerEncoded; } -/** @name ShardIdentifier */ -export interface ShardIdentifier extends Hash {} - -/** @name TrustedCall */ -export interface TrustedCall extends Enum { - readonly isBalanceTransfer: boolean; - readonly asBalanceTransfer: BalanceTransferArgs; - readonly isCeremoniesRegisterParticipant: boolean; - readonly asCeremoniesRegisterParticipant: RegisterParticipantArgs; - readonly isCeremoniesRegisterAttestations: boolean; - readonly asCeremoniesRegisterAttestations: RegisterAttestationsArgs; - readonly isCeremoniesGrantReputation: boolean; - readonly asCeremoniesGrantReputation: GrantReputationArgs; - readonly type: 'BalanceTransfer' | 'CeremoniesRegisterParticipant' | 'CeremoniesRegisterAttestations' | 'CeremoniesGrantReputation'; +/** @name RpcReturnValue */ +export interface RpcReturnValue extends Struct { + readonly value: Bytes; + readonly do_watch: bool; + readonly status: DirectRequestStatus; } -/** @name TrustedCallSigned */ -export interface TrustedCallSigned extends Struct { - readonly call: TrustedCall; - readonly nonce: u32; - readonly signature: Signature; -} +/** @name ShardIdentifier */ +export interface ShardIdentifier extends Hash {} -/** @name TrustedGetter */ -export interface TrustedGetter extends Enum { - readonly isBalance: boolean; - readonly asBalance: ITuple<[AccountId, CommunityIdentifier]>; - readonly isParticipantIndex: boolean; - readonly asParticipantIndex: ITuple<[AccountId, CommunityIdentifier]>; - readonly isMeetupIndex: boolean; - readonly asMeetupIndex: ITuple<[AccountId, CommunityIdentifier]>; - readonly isAttestations: boolean; - readonly asAttestations: ITuple<[AccountId, CommunityIdentifier]>; - readonly isMeetupRegistry: boolean; - readonly asMeetupRegistry: ITuple<[AccountId, CommunityIdentifier]>; - readonly type: 'Balance' | 'ParticipantIndex' | 'MeetupIndex' | 'Attestations' | 'MeetupRegistry'; +/** @name TrustedOperationStatus */ +export interface TrustedOperationStatus extends Enum { + readonly isSubmitted: boolean; + readonly isFuture: boolean; + readonly isReady: boolean; + readonly isBroadCast: boolean; + readonly isInSidechainBlock: boolean; + readonly asInSidechainBlock: Hash; + readonly isRetracted: boolean; + readonly isFinalityTimeout: boolean; + readonly isFinalized: boolean; + readonly isUsurped: boolean; + readonly isDropped: boolean; + readonly isInvalid: boolean; + readonly type: 'Submitted' | 'Future' | 'Ready' | 'BroadCast' | 'InSidechainBlock' | 'Retracted' | 'FinalityTimeout' | 'Finalized' | 'Usurped' | 'Dropped' | 'Invalid'; } -/** @name TrustedGetterSigned */ -export interface TrustedGetterSigned extends Struct { - readonly getter: TrustedGetter; - readonly signature: Signature; -} +/** @name Vault */ +export interface Vault extends ITuple<[AccountId, ParentchainId]> {} /** @name WorkerEncoded */ export interface WorkerEncoded extends Bytes {} diff --git a/packages/worker-api/src/encointerWorker.spec.ts b/packages/worker-api/src/encointerWorker.spec.ts new file mode 100644 index 00000000..c8c230ad --- /dev/null +++ b/packages/worker-api/src/encointerWorker.spec.ts @@ -0,0 +1,132 @@ +import { Keyring } from '@polkadot/api'; +import { cryptoWaitReady } from '@polkadot/util-crypto'; +import { localDockerNetwork } from './testUtils/networks.js'; +import { EncointerWorker } from './encointerWorker.js'; +import WS from 'websocket'; + +const {w3cwebsocket: WebSocket} = WS; + +describe('worker', () => { + const network = localDockerNetwork(); + let keyring: Keyring; + let worker: EncointerWorker; + // let alice: KeyringPair; + // let charlie: KeyringPair; + beforeAll(async () => { + jest.setTimeout(90000); + await cryptoWaitReady(); + keyring = new Keyring({type: 'sr25519'}); + // alice = keyring.addFromUri('//Alice', {name: 'Alice default'}); + // charlie = keyring.addFromUri('//Charlie', {name: 'Bob default'}); + + worker = new EncointerWorker(network.worker, { + keyring: keyring, + types: network.customTypes, + // @ts-ignore + createWebSocket: (url) => new WebSocket( + url, + undefined, + undefined, + undefined, + // Allow the worker's self-signed certificate + { rejectUnauthorized: false } + ), + api: null, + }); + }); + + // skip it, as this requires a worker (and hence a node) to be running + // To my knowledge jest does not have an option to run skipped tests specifically, does it? + // Todo: add proper CI to test this too. + describe.skip('needs worker and node running', () => { + // Tests specific for the encointer protocol + describe('encointer-worker', () => { + describe('getTotalIssuance', () => { + it('should return value', async () => { + const result = await worker.getTotalIssuance(network.chosenCid); + // console.log('getTotalIssuance', result); + expect(result).toBeDefined(); + }); + }); + + describe('getParticipantCount', () => { + it('should return default value', async () => { + const result = await worker.getParticipantCount(network.chosenCid); + expect(result).toBe(0); + }); + }); + + describe('getMeetupCount', () => { + it('should return default value', async () => { + const result = await worker.getMeetupCount(network.chosenCid); + expect(result).toBe(0); + }); + }); + + describe('getCeremonyReward', () => { + it('should return default value', async () => { + const result = await worker.getCeremonyReward(network.chosenCid); + expect(result).toBe(1); + }); + }); + + describe('getLocationTolerance', () => { + it('should return default value', async () => { + const result = await worker.getLocationTolerance(network.chosenCid); + expect(result).toBe(1000); + }); + }); + + describe('getTimeTolerance', () => { + it('should return default value', async () => { + const result = await worker.getTimeTolerance(network.chosenCid); + expect(result.toNumber()).toBe(600000); + }); + }); + + describe('getSchedulerState', () => { + it('should return value', async () => { + const result = await worker.getSchedulerState(network.chosenCid); + // console.log('schedulerStateResult', result); + expect(result).toBeDefined(); + }); + }); + + describe('getRegistration', () => { + it('should return default value', async () => { + await cryptoWaitReady(); + const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); + const result = await worker.getParticipantIndex(bob, network.chosenCid); + expect(result.toNumber()).toBe(0); + }); + }); + + describe('getMeetupIndex', () => { + it('should return default value', async () => { + await cryptoWaitReady(); + const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); + const result = await worker.getMeetupIndex(bob, network.chosenCid); + expect(result.toNumber()).toBe(0); + }); + }); + + describe('getAttestations', () => { + it('should be empty', async () => { + await cryptoWaitReady(); + const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); + const result = await worker.getAttestations(bob, network.chosenCid); + expect(result.toJSON()).toStrictEqual([]); + }); + }); + + describe('getMeetupRegistry method', () => { + it('should be empty', async () => { + await cryptoWaitReady(); + const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); + const result = await worker.getMeetupRegistry(bob, network.chosenCid); + expect(result.toJSON()).toStrictEqual([]); + }); + }); + }); + }); +}); diff --git a/packages/worker-api/src/encointerWorker.ts b/packages/worker-api/src/encointerWorker.ts new file mode 100644 index 00000000..efbfe4e1 --- /dev/null +++ b/packages/worker-api/src/encointerWorker.ts @@ -0,0 +1,110 @@ +import type {u32, u64, Vec} from '@polkadot/types'; +import {communityIdentifierFromString} from '@encointer/util'; + +// @ts-ignore +import NodeRSA from 'node-rsa'; + +import type { + CommunityIdentifier, + MeetupIndexType, + ParticipantIndexType, + SchedulerState, + Attestation, +} from '@encointer/types'; + +import {type CallOptions, Request} from './interface.js'; +import {callGetter} from './sendRequest.js'; +import {PubKeyPinPair, toAccount} from "@encointer/util/common"; +import type {KeyringPair} from "@polkadot/keyring/types"; +import {Worker} from "@encointer/worker-api/worker.js"; +import type {AccountId, Balance, Moment} from "@polkadot/types/interfaces/runtime"; + +// Todo: This code is a WIP and will not work as is: https://github.com/encointer/encointer-js/issues/91 + +export class EncointerWorker extends Worker { + + public cidFromStr(cidStr: String): CommunityIdentifier { + return communityIdentifierFromString(this.registry(), cidStr); + } + + public async getNonce(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.TrustedGetter, 'nonce', 'u32'], { + shard: cid, + account: toAccount(accountOrPubKey, this.keyring()) + }, options) + } + + public async getTotalIssuance(cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.PublicGetter, 'total_issuance', 'Balance'], {cid}, options) + } + + public async getParticipantCount(cid: string, options: CallOptions = {} as CallOptions): Promise { + return (await callGetter(this, [Request.PublicGetter, 'participant_count', 'u64'], {cid}, options)).toNumber() + } + + public async getMeetupCount(cid: string, options: CallOptions = {} as CallOptions): Promise { + return (await callGetter(this, [Request.PublicGetter, 'meetup_count', 'u64'], {cid}, options)).toNumber() + } + + public async getCeremonyReward(cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.PublicGetter, 'ceremony_reward', 'I64F64'], {cid}, options) + } + + public async getLocationTolerance(cid: string, options: CallOptions = {} as CallOptions): Promise { + return (await callGetter(this, [Request.PublicGetter, 'location_tolerance', 'u32'], {cid}, options)).toNumber() + } + + public async getTimeTolerance(cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.PublicGetter, 'time_tolerance', 'Moment'], {cid}, options) + } + + public async getSchedulerState(cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.PublicGetter, 'scheduler_state', 'SchedulerState'], {cid}, options) + } + + public async getBalance(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.TrustedGetter, 'free_balance', 'Balance'], { + shard: cid, + account: toAccount(accountOrPubKey,this.keyring()) + }, options) + } + + public async getParticipantIndex(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.TrustedGetter, 'participant_index', 'ParticipantIndexType'], { + cid, + account: toAccount(accountOrPubKey,this.keyring()) + }, options) + } + + public async getMeetupIndex(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.TrustedGetter, 'meetup_index', 'MeetupIndexType'], { + cid, + account: toAccount(accountOrPubKey,this.keyring()) + }, options) + } + + public async getAttestations(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise> { + return await callGetter>(this, [Request.TrustedGetter, 'attestations', 'Vec'], { + cid, + account: toAccount(accountOrPubKey,this.keyring()) + }, options) + } + + public async getMeetupRegistry(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise> { + return await callGetter>(this, [Request.TrustedGetter, 'meetup_registry', 'Vec'], { + cid, + account: toAccount(accountOrPubKey, this.keyring()) + }, options) + } + + // Todo: `sendTrustedCall` must be generic over the trusted call or we have to duplicate code for encointer. + // async sendTrustedCall(call: EncointerTrustedCallSigned, shard: ShardIdentifier, options: CallOptions = {} as CallOptions): Promise { + // if (this.shieldingKey() == undefined) { + // const key = await this.getShieldingKey(options); + // console.log(`Setting the shielding pubKey of the worker.`) + // this.setShieldingKey(key); + // } + // + // return sendTrustedCall(this, call, shard, true, 'TrustedOperationResult', options); + // } +} diff --git a/packages/worker-api/src/getterApi.ts b/packages/worker-api/src/getterApi.ts deleted file mode 100644 index 0ef66cd4..00000000 --- a/packages/worker-api/src/getterApi.ts +++ /dev/null @@ -1,80 +0,0 @@ -import type { IEncointerWorker, TrustedGetterArgs, PublicGetterArgs, RequestArgs, CallOptions, WorkerMethod } from './interface.js'; -import { Request } from './interface.js'; - -const sendWorkerRequest = (self: IEncointerWorker, clientRequest: any, parserType: string, options: CallOptions): Promise =>{ - const requestId = self.rqStack.push(parserType) + self.rsCount; - return self.sendRequest( - clientRequest, { - timeout: options.timeout, - requestId - } - ) -} - -const clientRequest = (self: IEncointerWorker, request: string) => { - return self.createType( 'ClientRequest', { - [request]: null - }); -} - -const clientRequestGetter = (self: IEncointerWorker, request: string, args: PublicGetterArgs) => { - const { cid } = args; - const getter = self.createType('PublicGetter', { - [request]: cid - }); - return { - StfState: [{ public: getter }, cid] - } -} -const requestParams = (self: IEncointerWorker, address: string, shard: string) => - self.createType('(AccountId, CommunityIdentifier)', [address, shard]); - -const clientRequestTrustedGetter = (self: IEncointerWorker, request: string, args: TrustedGetterArgs) => { - const {cid, account} = args; - const address = account.address; - const getter = self.createType('TrustedGetter', { - [request]: requestParams(self, address, cid) - }); - const signature = account.sign(getter.toU8a()); - return { - StfState: [ - { - trusted: { - getter, - signature - } - }, - cid - ] - } -} - -const sendTrustedRequest = (self: IEncointerWorker, method: string, parser: string, args: TrustedGetterArgs, options: CallOptions) => - sendWorkerRequest(self, clientRequestTrustedGetter(self, method, args), parser, options) - -const sendPublicRequest = (self: IEncointerWorker, method: string, parser: string, args: PublicGetterArgs, options: CallOptions) => - sendWorkerRequest(self, clientRequestGetter(self, method, args), parser, options) - -export const callGetter = async (self: IEncointerWorker, workerMethod: WorkerMethod, args: RequestArgs, options: CallOptions = {} as CallOptions): Promise => { - if( !self.isOpened ) { - await self.open(); - } - const [getterType, method, parser] = workerMethod; - let result: Promise; - let parserType: string = options.debug ? 'raw': parser; - switch (getterType) { - case Request.TrustedGetter: - result = sendTrustedRequest(self, method, parserType, args as TrustedGetterArgs, options) - break; - case Request.PublicGetter: - result = sendPublicRequest(self, method, parserType, args as PublicGetterArgs, options) - break; - case Request.Worker: - result = sendWorkerRequest(self, clientRequest(self, method), parserType, options) - break; - default: - result = sendPublicRequest(self, method, parserType, args as PublicGetterArgs, options) - break; - } - return result as Promise -} diff --git a/packages/worker-api/src/index.ts b/packages/worker-api/src/index.ts index 78d32b95..90f94eda 100644 --- a/packages/worker-api/src/index.ts +++ b/packages/worker-api/src/index.ts @@ -1,3 +1,5 @@ -export { EncointerWorker } from './worker.js'; +export { Worker } from './worker.js'; +export { EncointerWorker } from './encointerWorker.js'; +export { IntegriteeWorker } from './integriteeWorker.js'; export * from './interface.js'; diff --git a/packages/worker-api/src/integriteeWorker.spec.ts b/packages/worker-api/src/integriteeWorker.spec.ts new file mode 100644 index 00000000..a01435ff --- /dev/null +++ b/packages/worker-api/src/integriteeWorker.spec.ts @@ -0,0 +1,96 @@ +import { Keyring } from '@polkadot/api'; +import { cryptoWaitReady } from '@polkadot/util-crypto'; +import { localDockerNetwork } from './testUtils/networks.js'; +import { IntegriteeWorker } from './integriteeWorker.js'; +import WS from 'websocket'; +import {type KeyringPair} from "@polkadot/keyring/types"; +import bs58 from "bs58"; + +const {w3cwebsocket: WebSocket} = WS; + +describe('worker', () => { + const network = localDockerNetwork(); + let keyring: Keyring; + let worker: IntegriteeWorker; + let alice: KeyringPair; + let charlie: KeyringPair; + beforeAll(async () => { + jest.setTimeout(90000); + await cryptoWaitReady(); + keyring = new Keyring({type: 'sr25519'}); + alice = keyring.addFromUri('//Alice', {name: 'Alice default'}); + charlie = keyring.addFromUri('//Charlie', {name: 'Bob default'}); + + worker = new IntegriteeWorker(network.worker, { + keyring: keyring, + types: network.customTypes, + // @ts-ignore + createWebSocket: (url) => new WebSocket( + url, + undefined, + undefined, + undefined, + // Allow the worker's self-signed certificate + { rejectUnauthorized: false } + ), + api: null, + }); + }); + + // skip it, as this requires a worker (and hence a node) to be running + // To my knowledge jest does not have an option to run skipped tests specifically, does it? + // Todo: add proper CI to test this too. + describe.skip('needs worker and node running', () => { + describe('getWorkerPubKey', () => { + it('should return value', async () => { + const result = await worker.getShieldingKey(); + // console.log('Shielding Key', result); + expect(result).toBeDefined(); + }); + }); + + describe('getShardVault', () => { + it('should return value', async () => { + const result = await worker.getShardVault(); + console.log('ShardVault', result.toHuman()); + expect(result).toBeDefined(); + }); + }); + + describe('getBalance', () => { + it('should return value', async () => { + const result = await worker.getBalance(charlie, network.mrenclave); + console.log('getBalance toNumber:', result.toString(10)); + expect(result).toBeDefined(); + }); + }); + + describe('getNonce', () => { + it('should return value', async () => { + const result = await worker.getNonce(alice, network.mrenclave); + console.log('getNonce', result); + expect(result).toBeDefined(); + }); + }); + + describe('balance transfer should work', () => { + it('should return value', async () => { + const shard = worker.createType('ShardIdentifier', bs58.decode(network.mrenclave)); + const params = worker.createType('BalanceTransferArgs', [alice.address, charlie.address, 1100000000000]) + const result = await worker.trustedBalanceTransfer(alice, shard, network.mrenclave, params); + console.log('balance transfer result', result.toHuman()); + expect(result).toBeDefined(); + }); + }); + + describe('balance unshield should work', () => { + it('should return value', async () => { + const shard = worker.createType('ShardIdentifier', bs58.decode(network.mrenclave)); + const params = worker.createType('BalanceUnshieldArgs', [alice.address, charlie.address, 1100000000000, shard]) + const result = await worker.balanceUnshieldFunds(alice, shard, network.mrenclave, params); + console.log('balance unshield result', result.toHuman()); + expect(result).toBeDefined(); + }); + }); + }); +}); diff --git a/packages/worker-api/src/integriteeWorker.ts b/packages/worker-api/src/integriteeWorker.ts new file mode 100644 index 00000000..ce955413 --- /dev/null +++ b/packages/worker-api/src/integriteeWorker.ts @@ -0,0 +1,57 @@ +import type {u32} from '@polkadot/types'; + +// @ts-ignore +import NodeRSA from 'node-rsa'; + + +import type {KeyringPair} from '@polkadot/keyring/types'; +import type {Balance, Hash} from '@polkadot/types/interfaces/runtime'; +import type { + BalanceTransferArgs, BalanceUnshieldArgs, + ShardIdentifier, IntegriteeTrustedCallSigned, +} from '@encointer/types'; + +import {type CallOptions, Request} from './interface.js'; +import {callGetter, sendTrustedCall} from './sendRequest.js'; +import {createTrustedCall} from "@encointer/worker-api/requests.js"; +import {PubKeyPinPair, toAccount} from "@encointer/util/common"; +import {Worker} from "@encointer/worker-api/worker.js"; + +export class IntegriteeWorker extends Worker { + + public async getNonce(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.TrustedGetter, 'nonce', 'u32'], { + shard: cid, + account: toAccount(accountOrPubKey, this.keyring()) + }, options) + } + + public async getBalance(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.TrustedGetter, 'free_balance', 'Balance'], { + shard: cid, + account: toAccount(accountOrPubKey, this.keyring()) + }, options) + } + + public async trustedBalanceTransfer(accountOrPubKey: KeyringPair | PubKeyPinPair, shard: ShardIdentifier, mrenclave: string, params: BalanceTransferArgs, options: CallOptions = {} as CallOptions): Promise { + const nonce = await this.getNonce(accountOrPubKey, mrenclave, options); + const call = createTrustedCall(this, ['balance_transfer', 'BalanceTransferArgs'], accountOrPubKey, shard, mrenclave, nonce, params); + return this.sendTrustedCall(call, shard, options); + } + + public async balanceUnshieldFunds(accountOrPubKey: KeyringPair | PubKeyPinPair, shard: ShardIdentifier, mrenclave: string, params: BalanceUnshieldArgs, options: CallOptions = {} as CallOptions): Promise { + const nonce = await this.getNonce(accountOrPubKey, mrenclave, options); + const call = createTrustedCall(this, ['balance_unshield', 'BalanceUnshieldArgs'], accountOrPubKey, shard, mrenclave, nonce, params); + return this.sendTrustedCall(call, shard, options); + } + + async sendTrustedCall(call: IntegriteeTrustedCallSigned, shard: ShardIdentifier, options: CallOptions = {} as CallOptions): Promise { + if (this.shieldingKey() == undefined) { + const key = await this.getShieldingKey(options); + console.log(`Setting the shielding pubKey of the worker.`) + this.setShieldingKey(key); + } + + return sendTrustedCall(this, call, shard, true, 'TrustedOperationResult', options); + } +} diff --git a/packages/worker-api/src/interface.ts b/packages/worker-api/src/interface.ts index 03d1338b..b335fb24 100644 --- a/packages/worker-api/src/interface.ts +++ b/packages/worker-api/src/interface.ts @@ -1,13 +1,33 @@ import type { KeyringPair } from '@polkadot/keyring/types'; import WebSocketAsPromised from 'websocket-as-promised'; import {Keyring} from "@polkadot/keyring"; +import type {u8} from "@polkadot/types-codec"; +import type {TypeRegistry, Vec} from "@polkadot/types"; -export interface IEncointerWorker extends WebSocketAsPromised { +export interface IWorker extends WebSocketAsPromised { rsCount: number; rqStack: string[]; keyring: () => Keyring | undefined; createType: (apiType: string, obj?: any) => any; open: () => Promise; + encrypt: (data: Uint8Array) => Vec + registry: () => TypeRegistry +} + +export interface JsonRpcRequest { + jsonrpc: string; + method: string; + params?: any; + id: number | string; +} + +export function createJsonRpcRequest(method: string, params: any, id: number | string): JsonRpcRequest { + return { + jsonrpc: '2.0', + method: method, + params: params, + id: id + }; } export interface WorkerOptions { @@ -18,7 +38,7 @@ export interface WorkerOptions { } export interface TrustedGetterArgs { - cid: string; + shard: string; account: KeyringPair; } @@ -26,7 +46,7 @@ export interface PublicGetterArgs { cid: string; } -export type RequestArgs = PublicGetterArgs | TrustedGetterArgs | { } +export type RequestArgs = PublicGetterArgs | TrustedGetterArgs | { } export interface CallOptions { timeout: number; diff --git a/packages/worker-api/src/parsers.ts b/packages/worker-api/src/parsers.ts index 1f50ab22..b6b90ca5 100644 --- a/packages/worker-api/src/parsers.ts +++ b/packages/worker-api/src/parsers.ts @@ -4,10 +4,10 @@ import { u8aToBn, u8aToBuffer } from '@polkadot/util'; // @ts-ignore import NodeRSA from 'node-rsa'; -import type { IEncointerWorker } from './interface.js'; +import type { IWorker } from './interface.js'; import type { BalanceEntry } from "@encointer/types"; -export function parseBalance(self: IEncointerWorker, data: any): BalanceEntry { +export function parseBalance(self: IWorker, data: any): BalanceEntry { const balanceEntry = self.createType('BalanceEntry', data); // Todo: apply demurrage return self.createType('BalanceEntry', @@ -38,6 +38,10 @@ export function parseNodeRSA(data: any): NodeRSA { function setKeyOpts(key: NodeRSA) { key.setOptions( { + // Enforce using the pure javascript implementations by + // setting the `browser` environment, as compatibility + // with node's crypto is broken and leads to bad outputs. + environment: 'browser', encryptionScheme: { scheme: 'pkcs1_oaep', hash: 'sha256', diff --git a/packages/worker-api/src/requests.ts b/packages/worker-api/src/requests.ts new file mode 100644 index 00000000..511affdb --- /dev/null +++ b/packages/worker-api/src/requests.ts @@ -0,0 +1,88 @@ +import { + createJsonRpcRequest, + type IWorker, type PublicGetterArgs, + type TrustedGetterArgs +} from "@encointer/worker-api/interface.js"; +import type {BalanceTransferArgs, BalanceUnshieldArgs, ShardIdentifier, IntegriteeTrustedCallSigned} from "@encointer/types"; +import type {KeyringPair} from "@polkadot/keyring/types"; +import {type PubKeyPinPair, toAccount} from "@encointer/util/common.js"; +import type {u32} from "@polkadot/types"; +import bs58 from "bs58"; + +// Todo: Properly resolve cid vs shard +export const clientRequestGetter = (self: IWorker, request: string, args: PublicGetterArgs) => { + const { cid } = args; + const getter = self.createType('IntegriteePublicGetter', { + [request]: cid + }); + + const g = self.createType( 'IntegriteeGetter',{ + public: { + getter, + } + }); + + const r = self.createType( + 'Request', { shard: cid, cyphertext: g.toU8a() } + ); + + return createJsonRpcRequest('state_executeGetter', [r.toHex()],1); +} + +export const clientRequestTrustedGetter = (self: IWorker, request: string, args: TrustedGetterArgs) => { + const {shard, account} = args; + const address = account.address; + const getter = self.createType('IntegriteeTrustedGetter', { + [request]: address + }); + + const signature = account.sign(getter.toU8a()); + const g = self.createType( 'IntegriteeGetter',{ + trusted: { + getter, + signature: { Sr25519: signature }, + } + }); + + console.log(`TrustedGetter: ${JSON.stringify(g)}`); + + const s = self.createType('ShardIdentifier', bs58.decode(shard)); + const r = self.createType( + 'Request', { + shard: s, + cyphertext: g.toHex() + } + ); + + return createJsonRpcRequest('state_executeGetter', [r.toHex()],1); +} + +export type TrustedCallArgs = (BalanceTransferArgs | BalanceUnshieldArgs); + +export type TrustedCallVariant = [string, string] + +export const createTrustedCall = ( + self: IWorker, + trustedCall: TrustedCallVariant, + accountOrPubKey: (KeyringPair | PubKeyPinPair), + shard: ShardIdentifier, + mrenclave: string, + nonce: u32, + params: TrustedCallArgs +): IntegriteeTrustedCallSigned => { + + const [variant, argType] = trustedCall; + const hash = self.createType('Hash', bs58.decode(mrenclave)); + + const call = self.createType('IntegriteeTrustedCall', { + [variant]: self.createType(argType, params) + }); + + const payload = Uint8Array.from([...call.toU8a(), ...nonce.toU8a(), ...hash.toU8a(), ...shard.toU8a()]); + + return self.createType('IntegriteeIntegriteeTrustedCallSigned', { + call: call, + nonce: nonce, + signature: { Sr25519: toAccount(accountOrPubKey, self.keyring()).sign(payload) }, + }); +} diff --git a/packages/worker-api/src/sendRequest.ts b/packages/worker-api/src/sendRequest.ts new file mode 100644 index 00000000..b4a5dd5c --- /dev/null +++ b/packages/worker-api/src/sendRequest.ts @@ -0,0 +1,89 @@ +import { + type IWorker, + type TrustedGetterArgs, + type PublicGetterArgs, + type RequestArgs, + type CallOptions, + type WorkerMethod, + createJsonRpcRequest +} from './interface.js'; +import { Request } from './interface.js'; +import { + clientRequestGetter, + clientRequestTrustedGetter, +} from "@encointer/worker-api/requests.js"; +import type {ShardIdentifier, IntegriteeTrustedCallSigned} from "@encointer/types"; + +const sendWorkerRequest = (self: IWorker, clientRequest: any, parserType: string, options: CallOptions): Promise =>{ + const requestId = self.rqStack.push(parserType) + self.rsCount; + return self.sendRequest( + clientRequest, { + timeout: options.timeout, + requestId + } + ) +} + +const sendTrustedGetterRequest = (self: IWorker, method: string, parser: string, args: TrustedGetterArgs, options: CallOptions) => + sendWorkerRequest(self, clientRequestTrustedGetter(self, method, args), parser, options) + +const sendPublicGetterRequest = (self: IWorker, method: string, parser: string, args: PublicGetterArgs, options: CallOptions) => + sendWorkerRequest(self, clientRequestGetter(self, method, args), parser, options) + +export const callGetter = async (self: IWorker, workerMethod: WorkerMethod, args: RequestArgs, options: CallOptions = {} as CallOptions): Promise => { + if( !self.isOpened ) { + await self.open(); + } + const [getterType, method, parser] = workerMethod; + let result: Promise; + let parserType: string = options.debug ? 'raw': parser; + switch (getterType) { + case Request.TrustedGetter: + result = sendTrustedGetterRequest(self, method, parserType, args as TrustedGetterArgs, options) + break; + case Request.PublicGetter: + result = sendPublicGetterRequest(self, method, parserType, args as PublicGetterArgs, options) + break; + case Request.Worker: + result = sendWorkerRequest(self, createJsonRpcRequest(method, [], 1), parserType, options) + break; + default: + result = sendPublicGetterRequest(self, method, parserType, args as PublicGetterArgs, options) + break; + } + return result as Promise +} + +export const sendTrustedCall = async (self: IWorker, call: IntegriteeTrustedCallSigned, shard: ShardIdentifier, direct: boolean, parser: string, options: CallOptions = {} as CallOptions): Promise => { + if( !self.isOpened ) { + await self.open(); + } + + let result: Promise; + let parserType: string = options.debug ? 'raw': parser; + + console.log(`TrustedCall: ${JSON.stringify(call)}`); + + let top; + if (direct) { + top = self.createType('IntegriteeTrustedOperation', { + direct_call: call + }) + } else { + top = self.createType('IntegriteeTrustedOperation', { + indirect_call: call + }) + } + + console.log(`TrustedOperation: ${JSON.stringify(top)}`); + + const cyphertext = self.encrypt(top.toU8a()); + + const r = self.createType( + 'Request', { shard, cyphertext: cyphertext } + ); + + result = sendWorkerRequest(self, createJsonRpcRequest('author_submitExtrinsic', [r.toHex()], 1), parserType, options) + return result as Promise +} + diff --git a/packages/worker-api/src/testUtils/networks.ts b/packages/worker-api/src/testUtils/networks.ts index f89dd907..e7ea96c6 100644 --- a/packages/worker-api/src/testUtils/networks.ts +++ b/packages/worker-api/src/testUtils/networks.ts @@ -36,13 +36,13 @@ export const chainbrickNetwork = () => { // Note: `mrenclave` is not deterministic, this needs to be edited for every worker build. export const localDockerNetwork = () => { return { - chain: 'ws://127.0.0.1:9979', - worker: 'ws://127.0.0.1:2079', + chain: 'ws://127.0.0.1:9944', + worker: 'wss://127.0.0.1:2000', genesisHash: '0x388c446a804e24e77ae89f5bb099edb60cacc2ac7c898ce175bdaa08629c1439', - mrenclave: '4SkU25tusVChcrUprW8X22QoEgamCgj3HKQeje7j8Z4E', + mrenclave: 'HjkQuPjBn531Hkji2Dsj4CEYCGpqCc3aXqETMCM7x7z4', chosenCid: '4Xgnkpg4RwXjFegLzYKgY6Y3jCSPmxyPmNvfs42Uvsuh', - customTypes: TypeOverrides_V3_8, - palletOverrides: PalletOverrides_V3_8 + customTypes: {}, + palletOverrides: {} }; }; diff --git a/packages/worker-api/src/trustedCallApi.ts b/packages/worker-api/src/trustedCallApi.ts deleted file mode 100644 index 7bf1d2e8..00000000 --- a/packages/worker-api/src/trustedCallApi.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { IEncointerWorker } from "./interface.js" -import type { - BalanceTransferArgs, CommunityIdentifier, - GrantReputationArgs, - RegisterAttestationsArgs, - RegisterParticipantArgs, - TrustedCallSigned -} from "@encointer/types"; -import type { KeyringPair } from "@polkadot/keyring/types"; -import type { u32 } from "@polkadot/types"; -import bs58 from "bs58"; -import { toAccount, PubKeyPinPair } from "@encointer/util/common"; - -export type TrustedCallArgs = (BalanceTransferArgs | RegisterParticipantArgs | RegisterAttestationsArgs | GrantReputationArgs); - -export type TrustedCallVariant = [string, string] - -export const createTrustedCall = ( - self: IEncointerWorker, - trustedCall: TrustedCallVariant, - accountOrPubKey: (KeyringPair | PubKeyPinPair), - cid: CommunityIdentifier, - mrenclave: string, - nonce: u32, - params: TrustedCallArgs -): TrustedCallSigned => { - - const [variant, argType] = trustedCall; - const hash = self.createType('Hash', bs58.decode(mrenclave)); - - const call = self.createType('TrustedCall', { - [variant]: self.createType(argType, params) - }); - - const payload = Uint8Array.from([...call.toU8a(), ...nonce.toU8a(), ...hash.toU8a(), ...cid.toU8a()]); - - return self.createType('TrustedCallSigned', { - call: call, - nonce: nonce, - signature: toAccount(accountOrPubKey, self.keyring()).sign(payload) - }); -} diff --git a/packages/worker-api/src/worker.spec.ts b/packages/worker-api/src/worker.spec.ts index 73aec95b..07972d29 100644 --- a/packages/worker-api/src/worker.spec.ts +++ b/packages/worker-api/src/worker.spec.ts @@ -1,58 +1,36 @@ import { Keyring } from '@polkadot/api'; import { cryptoWaitReady } from '@polkadot/util-crypto'; import { localDockerNetwork } from './testUtils/networks.js'; -import { EncointerWorker } from './worker.js'; +import { Worker } from './worker.js'; import WS from 'websocket'; -import type { CommunityIdentifier } from "@encointer/types"; const {w3cwebsocket: WebSocket} = WS; describe('worker', () => { const network = localDockerNetwork(); let keyring: Keyring; - let worker: EncointerWorker; + let worker: Worker; beforeAll(async () => { jest.setTimeout(90000); await cryptoWaitReady(); keyring = new Keyring({type: 'sr25519'}); - const keypair = keyring.addFromUri('//Bob'); - const json = keypair.toJson('1234'); - keypair.lock(); - keyring.addFromJson(json); - worker = new EncointerWorker(network.worker, { + worker = new Worker(network.worker, { keyring: keyring, types: network.customTypes, // @ts-ignore - createWebSocket: (url) => new WebSocket(url), + createWebSocket: (url) => new WebSocket( + url, + undefined, + undefined, + undefined, + // Allow the worker's self-signed certificate + { rejectUnauthorized: false } + ), api: null, }); }); - describe('trusted call', () => { - it('ceremonies_register_participant is valid', () => { - const alice = keyring.addFromUri('//Alice'); - const proof = worker.createType('Option>'); - const cid: CommunityIdentifier = worker.cidFromStr('gbsuv7YXq9G'); - const nonce = worker.createType('u32', 0) - const args = worker.createType('RegisterParticipantArgs', [alice.publicKey, cid, proof]) - - // trustedCall from the previous js-implementation that is known to work. - const tCallHex = '0x01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d6762737576ffffffff0000000000940cf3e675d8bd25066ad8a15af580ca9a41d3b13f840f43647f51869875fb62232086204dffc8ee67d959e2e3135eae214dd6296e76706459f6c9c8f2b3be86' - - const call = worker.trustedCallRegisterParticipant( - alice, - cid, - network.mrenclave, - nonce, - args - ); - - // the last 64 bytes are from the non-deterministic signature - expect(call.toHex().slice(0, -128)).toEqual(tCallHex.slice(0, -128)); - }) - }) - // skip it, as this requires a worker (and hence a node) to be running // To my knowledge jest does not have an option to run skipped tests specifically, does it? // Todo: add proper CI to test this too. @@ -65,102 +43,12 @@ describe('worker', () => { }); }); - describe('getTotalIssuance', () => { + describe('getShardVault', () => { it('should return value', async () => { - const result = await worker.getTotalIssuance(network.chosenCid); - // console.log('getTotalIssuance', result); + const result = await worker.getShardVault(); + console.log('ShardVault', result.toHuman()); expect(result).toBeDefined(); }); }); - - describe('getParticipantCount', () => { - it('should return default value', async () => { - const result = await worker.getParticipantCount(network.chosenCid); - expect(result).toBe(0); - }); - }); - - describe('getMeetupCount', () => { - it('should return default value', async () => { - const result = await worker.getMeetupCount(network.chosenCid); - expect(result).toBe(0); - }); - }); - - describe('getCeremonyReward', () => { - it('should return default value', async () => { - const result = await worker.getCeremonyReward(network.chosenCid); - expect(result).toBe(1); - }); - }); - - describe('getLocationTolerance', () => { - it('should return default value', async () => { - const result = await worker.getLocationTolerance(network.chosenCid); - expect(result).toBe(1000); - }); - }); - - describe('getTimeTolerance', () => { - it('should return default value', async () => { - const result = await worker.getTimeTolerance(network.chosenCid); - expect(result.toNumber()).toBe(600000); - }); - }); - - describe('getSchedulerState', () => { - it('should return value', async () => { - const result = await worker.getSchedulerState(network.chosenCid); - // console.log('schedulerStateResult', result); - expect(result).toBeDefined(); - }); - }); - - describe('getBalance', () => { - it('should return value', async () => { - const result = await worker.getBalance({ - pubKey: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty', - pin: '1234' - }, network.chosenCid); - // console.log('getBalance', result); - expect(result).toBeDefined(); - }); - }); - - describe('getRegistration', () => { - it('should return default value', async () => { - await cryptoWaitReady(); - const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); - const result = await worker.getParticipantIndex(bob, network.chosenCid); - expect(result.toNumber()).toBe(0); - }); - }); - - describe('getMeetupIndex', () => { - it('should return default value', async () => { - await cryptoWaitReady(); - const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); - const result = await worker.getMeetupIndex(bob, network.chosenCid); - expect(result.toNumber()).toBe(0); - }); - }); - - describe('getAttestations', () => { - it('should be empty', async () => { - await cryptoWaitReady(); - const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); - const result = await worker.getAttestations(bob, network.chosenCid); - expect(result.toJSON()).toStrictEqual([]); - }); - }); - - describe('getMeetupRegistry method', () => { - it('should be empty', async () => { - await cryptoWaitReady(); - const bob = keyring.addFromUri('//Bob', {name: 'Bob default'}); - const result = await worker.getMeetupRegistry(bob, network.chosenCid); - expect(result.toJSON()).toStrictEqual([]); - }); - }); }); }); diff --git a/packages/worker-api/src/worker.ts b/packages/worker-api/src/worker.ts index 24118c04..ac8c08a0 100644 --- a/packages/worker-api/src/worker.ts +++ b/packages/worker-api/src/worker.ts @@ -1,69 +1,80 @@ -import { TypeRegistry } from '@polkadot/types'; -import type { RegistryTypes } from '@polkadot/types/types'; -import { Keyring } from '@polkadot/keyring' -import { hexToU8a, u8aToHex } from '@polkadot/util'; +import type {Vec} from '@polkadot/types'; +import {TypeRegistry} from '@polkadot/types'; +import type {RegistryTypes} from '@polkadot/types/types'; +import {Keyring} from '@polkadot/keyring' +import {bufferToU8a, compactAddLength, hexToU8a, u8aToBuffer} from '@polkadot/util'; import WebSocketAsPromised from 'websocket-as-promised'; -import { options as encointerOptions } from '@encointer/node-api'; -import {communityIdentifierFromString, parseI64F64} from '@encointer/util'; +import {options as encointerOptions} from '@encointer/node-api'; +import {parseI64F64} from '@encointer/util'; // @ts-ignore import NodeRSA from 'node-rsa'; - -import type { KeyringPair } from '@polkadot/keyring/types'; -import type { Vec, u32, u64 } from '@polkadot/types'; -import type { AccountId, Balance, Moment } from '@polkadot/types/interfaces/runtime'; import type { - Attestation, BalanceEntry, BalanceTransferArgs, CommunityIdentifier, GrantReputationArgs, - MeetupIndexType, - ParticipantIndexType, RegisterAttestationsArgs, RegisterParticipantArgs, - SchedulerState, TrustedCallSigned + Vault } from '@encointer/types'; -import type { IEncointerWorker, WorkerOptions, CallOptions } from './interface.js'; -import { Request } from './interface.js'; -import { parseBalance, parseNodeRSA } from './parsers.js'; -import { callGetter } from './getterApi.js'; -import { createTrustedCall } from "@encointer/worker-api/trustedCallApi"; -import { toAccount, PubKeyPinPair } from "@encointer/util/common"; +import {type CallOptions, type IWorker, Request, type WorkerOptions} from './interface.js'; +import {parseBalance, parseNodeRSA} from './parsers.js'; +import {callGetter} from './sendRequest.js'; +import type {u8} from "@polkadot/types-codec"; -const unwrapWorkerResponse = (self: IEncointerWorker, data: string) => { - /// Unwraps the value that is wrapped in all the Options and encoding from the worker. +const unwrapWorkerResponse = (self: IWorker, data: string) => { /// Defaults to return `[]`, which is fine as `createType(api.registry, , [])` /// instantiates the with its default value. - const dataTyped = self.createType('Option', hexToU8a('0x'.concat(data))) - .unwrapOrDefault(); // (Option.enc+whitespacePad) - const trimmed = u8aToHex(dataTyped).replace(/(20)+$/, ''); - const unwrappedData = self.createType('Option', hexToU8a(trimmed)) - .unwrapOrDefault(); - return unwrappedData + const dataTyped = self.createType('Option', data) + return dataTyped.unwrapOrDefault(); } -const parseGetterResponse = (self: IEncointerWorker, responseType: string, data: string) => { +const parseGetterResponse = (self: IWorker, responseType: string, data: string) => { if (data === 'Could not decode request') { throw new Error(`Worker error: ${data}`); } + + console.log(`Getter response: ${data}`); + const json = JSON.parse(data); + + const value = hexToU8a(json["result"]); + const returnValue = self.createType('RpcReturnValue', value); + console.log(`RpcReturnValue ${JSON.stringify(returnValue)}`); + + if (returnValue.status.isError) { + const errorMsg = self.createType('String', returnValue.value); + throw new Error(`RPC Error: ${errorMsg}`); + } + let parsedData: any; try { switch (responseType) { case 'raw': - parsedData = unwrapWorkerResponse(self, data); + parsedData = unwrapWorkerResponse(self, returnValue.value); break; case 'BalanceEntry': - parsedData = unwrapWorkerResponse(self, data); + parsedData = unwrapWorkerResponse(self, returnValue.value); parsedData = parseBalance(self, parsedData); break; case 'I64F64': - parsedData = unwrapWorkerResponse(self, data); + parsedData = unwrapWorkerResponse(self, returnValue.value); parsedData = parseI64F64(self.createType('i128', parsedData)); break; case 'NodeRSA': - parsedData = parseNodeRSA(data); + const jsonStr = self.createType('String', returnValue.value); + // Todo: For some reason there are 2 non-utf characters, where I don't know where + // they come from currently. + console.log(`Got shielding key: ${jsonStr.toJSON().substring(2)}`); + parsedData = parseNodeRSA(jsonStr.toJSON().substring(2)); + break + case 'Vault': + parsedData = self.createType(responseType, returnValue.value); + break + case 'TrustedOperationResult': + parsedData = self.createType('Hash', returnValue.value); break default: - parsedData = unwrapWorkerResponse(self, data); + parsedData = unwrapWorkerResponse(self, returnValue.value); + console.log(`unwrapped data ${parsedData}`); parsedData = self.createType(responseType, parsedData); break; } @@ -73,12 +84,14 @@ const parseGetterResponse = (self: IEncointerWorker, responseType: string, data: return parsedData; } -export class EncointerWorker extends WebSocketAsPromised implements IEncointerWorker { +export class Worker extends WebSocketAsPromised implements IWorker { readonly #registry: TypeRegistry; #keyring?: Keyring; + #shieldingKey?: NodeRSA + rsCount: number; rqStack: string[]; @@ -86,7 +99,7 @@ export class EncointerWorker extends WebSocketAsPromised implements IEncointerWo constructor(url: string, options: WorkerOptions = {} as WorkerOptions) { super(url, { createWebSocket: (options.createWebSocket || undefined), - packMessage: (data: any) => this.createType('ClientRequest', data).toU8a(), + packMessage: (data: any) => JSON.stringify(data), unpackMessage: (data: any) => parseGetterResponse(this, this.rqStack.shift() || '', data), attachRequestId: (data: any): any => data, extractRequestId: () => this.rsCount = ++this.rsCount @@ -105,6 +118,17 @@ export class EncointerWorker extends WebSocketAsPromised implements IEncointerWo } } + public encrypt(data: Uint8Array): Vec { + const buffer = u8aToBuffer(data); + const cypherTextBuffer = this.shieldingKey().encrypt(buffer); + const cypherArray = bufferToU8a(cypherTextBuffer); + return this.createType('Vec', compactAddLength(cypherArray)) + } + + public registry(): TypeRegistry { + return this.#registry + } + public createType(apiType: string, obj?: any): any { return this.#registry.createType(apiType as never, obj) } @@ -117,90 +141,19 @@ export class EncointerWorker extends WebSocketAsPromised implements IEncointerWo this.#keyring = keyring; } - public cidFromStr(cidStr: String): CommunityIdentifier { - return communityIdentifierFromString(this.#registry, cidStr); - } - - public async getShieldingKey(options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.Worker, 'PubKeyWorker', 'NodeRSA'], {}, options) - } - - public async getTotalIssuance(cid: string, options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.PublicGetter, 'total_issuance', 'Balance'], {cid}, options) - } - - public async getParticipantCount(cid: string, options: CallOptions = {} as CallOptions): Promise { - return (await callGetter(this, [Request.PublicGetter, 'participant_count', 'u64'], {cid}, options)).toNumber() - } - - public async getMeetupCount(cid: string, options: CallOptions = {} as CallOptions): Promise { - return (await callGetter(this, [Request.PublicGetter, 'meetup_count', 'u64'], {cid}, options)).toNumber() + public shieldingKey(): NodeRSA | undefined { + return this.#shieldingKey; } - public async getCeremonyReward(cid: string, options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.PublicGetter, 'ceremony_reward', 'I64F64'], {cid}, options) + public setShieldingKey(shieldingKey: NodeRSA): void { + this.#shieldingKey = shieldingKey; } - public async getLocationTolerance(cid: string, options: CallOptions = {} as CallOptions): Promise { - return (await callGetter(this, [Request.PublicGetter, 'location_tolerance', 'u32'], {cid}, options)).toNumber() - } - - public async getTimeTolerance(cid: string, options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.PublicGetter, 'time_tolerance', 'Moment'], {cid}, options) - } - - public async getSchedulerState(cid: string, options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.PublicGetter, 'scheduler_state', 'SchedulerState'], {cid}, options) - } - - public async getBalance(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.TrustedGetter, 'balance', 'BalanceEntry'], { - cid, - account: toAccount(accountOrPubKey, this.#keyring) - }, options) - } - - public async getParticipantIndex(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.TrustedGetter, 'participant_index', 'ParticipantIndexType'], { - cid, - account: toAccount(accountOrPubKey, this.#keyring) - }, options) - } - - public async getMeetupIndex(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise { - return await callGetter(this, [Request.TrustedGetter, 'meetup_index', 'MeetupIndexType'], { - cid, - account: toAccount(accountOrPubKey, this.#keyring) - }, options) - } - - public async getAttestations(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise> { - return await callGetter>(this, [Request.TrustedGetter, 'attestations', 'Vec'], { - cid, - account: toAccount(accountOrPubKey, this.#keyring) - }, options) - } - - public async getMeetupRegistry(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: string, options: CallOptions = {} as CallOptions): Promise> { - return await callGetter>(this, [Request.TrustedGetter, 'meetup_registry', 'Vec'], { - cid, - account: toAccount(accountOrPubKey, this.#keyring) - }, options) - } - - public trustedCallBalanceTransfer(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: CommunityIdentifier, mrenclave: string, nonce: u32, params: BalanceTransferArgs): TrustedCallSigned { - return createTrustedCall(this, ['balance_transfer', 'BalanceTransferArgs'], accountOrPubKey, cid, mrenclave, nonce, params) - } - - public trustedCallRegisterParticipant(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: CommunityIdentifier, mrenclave: string, nonce: u32, params: RegisterParticipantArgs): TrustedCallSigned { - return createTrustedCall(this, ['ceremonies_register_participant', 'RegisterParticipantArgs'], accountOrPubKey, cid, mrenclave, nonce, params) - } - - public trustedCallRegisterAttestations(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: CommunityIdentifier, mrenclave: string, nonce: u32, params: RegisterAttestationsArgs): TrustedCallSigned { - return createTrustedCall(this, ['ceremonies_register_attestations', 'RegisterAttestationsArgs'], accountOrPubKey, cid, mrenclave, nonce, params) + public async getShieldingKey(options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.Worker, 'author_getShieldingKey', 'NodeRSA'], {}, options) } - public trustedCallGrantReputation(accountOrPubKey: KeyringPair | PubKeyPinPair, cid: CommunityIdentifier, mrenclave: string, nonce: u32, params: GrantReputationArgs): TrustedCallSigned { - return createTrustedCall(this, ['ceremonies_grant_reputation', 'GrantReputationArgs'], accountOrPubKey, cid, mrenclave, nonce, params) + public async getShardVault(options: CallOptions = {} as CallOptions): Promise { + return await callGetter(this, [Request.Worker, 'author_getShardVault', 'Vault'], {}, options) } }