Skip to content

Commit d4e9ed4

Browse files
authored
Merge branch 'feature/forwards-compatibility' into forward-comp/account-info
2 parents e24293e + 4f20370 commit d4e9ed4

File tree

15 files changed

+444
-272
lines changed

15 files changed

+444
-272
lines changed

packages/sdk/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
### Breaking changes
1212

13+
- Renamed `TokenModuleRejectReason` to `EncodedTokenModuleRejectReason`, aligning with the corresponding types for
14+
`TokenModuleEvent`. `TokenModuleRejectReason` now describes the decoded version of `EncodedTokenModuleRejectReason`.
15+
1316
#### GRPC API query response types
1417

1518
- `BlockItemSummaryInBlock.summary` now has the type `Upward<BlockItemSummary>`.

packages/sdk/src/accountTransactions.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { Buffer } from 'buffer/index.js';
22

33
import { Cursor } from './deserializationHelpers.js';
4-
import { Cbor, TokenId } from './plt/index.js';
5-
import { TokenOperation, TokenOperationType } from './plt/module.js';
4+
import { Cbor, TokenId, TokenOperation, TokenOperationType } from './plt/index.js';
65
import { ContractAddress, ContractName, Energy, ModuleReference } from './pub/types.js';
76
import { serializeCredentialDeploymentInfo } from './serialization.js';
87
import {

packages/sdk/src/plt/Cbor.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import { Buffer } from 'buffer/index.js';
33
import * as Proto from '../grpc-api/v2/concordium/protocol-level-tokens.js';
44
import { HexString } from '../types.js';
55
import { cborDecode, cborEncode } from '../types/cbor.js';
6-
import { TokenAmount, TokenHolder, TokenMetadataUrl } from './index.js';
76
import {
8-
TokenInitializationParameters,
7+
TokenAmount,
8+
TokenHolder,
99
TokenListUpdateEventDetails,
10-
TokenModuleAccountState,
11-
TokenModuleState,
10+
TokenMetadataUrl,
1211
TokenPauseEventDetails,
13-
} from './module.js';
12+
} from './index.js';
13+
import { TokenInitializationParameters, TokenModuleAccountState, TokenModuleState } from './module.js';
1414

1515
export type JSON = HexString;
1616

packages/sdk/src/plt/Token.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,18 @@ import {
1212
import { AccountSigner, signTransaction } from '../signHelpers.js';
1313
import { SequenceNumber } from '../types/index.js';
1414
import { bail } from '../util.js';
15-
import { Cbor, TokenAmount, TokenHolder, TokenId, TokenInfo, TokenModuleReference } from './index.js';
1615
import {
16+
Cbor,
1717
TokenAddAllowListOperation,
1818
TokenAddDenyListOperation,
19+
TokenAmount,
1920
TokenBurnOperation,
21+
TokenHolder,
22+
TokenId,
23+
TokenInfo,
2024
TokenMintOperation,
2125
TokenModuleAccountState,
26+
TokenModuleReference,
2227
TokenModuleState,
2328
TokenOperation,
2429
TokenOperationType,
@@ -29,7 +34,7 @@ import {
2934
TokenTransferOperation,
3035
TokenUnpauseOperation,
3136
createTokenUpdatePayload,
32-
} from './module.js';
37+
} from './index.js';
3338

3439
/**
3540
* Enum representing the types of errors that can occur when interacting with PLT instances through the client.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { EncodedTokenModuleEvent, TransactionEventTag } from '../types.js';
2+
import { TokenOperationType } from './TokenOperation.js';
3+
import { Cbor, TokenHolder, TokenId } from './index.js';
4+
5+
type GenTokenModuleEvent<E extends TokenOperationType, T extends Object> = {
6+
/** The tag of the event. */
7+
tag: TransactionEventTag.TokenModuleEvent;
8+
/** The ID of the token. */
9+
tokenId: TokenId.Type;
10+
/** The type of the event. */
11+
type: E;
12+
/** The details of the event. */
13+
details: T;
14+
};
15+
16+
/**
17+
* The structure of any list update event for a PLT.
18+
*/
19+
export type TokenListUpdateEventDetails = {
20+
/** The target of the list update. */
21+
target: TokenHolder.Type;
22+
};
23+
24+
/**
25+
* The structure of a pause event for a PLT.
26+
*/
27+
export type TokenPauseEventDetails = {};
28+
29+
export type TokenEventDetails = TokenListUpdateEventDetails | TokenPauseEventDetails;
30+
31+
/**
32+
* An event occuring as the result of an "addAllowList" operation.
33+
*/
34+
export type TokenAddAllowListEvent = GenTokenModuleEvent<TokenOperationType.AddAllowList, TokenListUpdateEventDetails>;
35+
/**
36+
* An event occuring as the result of an "addDenyList" operation.
37+
*/
38+
export type TokenAddDenyListEvent = GenTokenModuleEvent<TokenOperationType.AddDenyList, TokenListUpdateEventDetails>;
39+
/**
40+
* An event occuring as the result of an "removeAllowList" operation.
41+
*/
42+
export type TokenRemoveAllowListEvent = GenTokenModuleEvent<
43+
TokenOperationType.RemoveAllowList,
44+
TokenListUpdateEventDetails
45+
>;
46+
/**
47+
* An event occuring as the result of an "removeDenyList" operation.
48+
*/
49+
export type TokenRemoveDenyListEvent = GenTokenModuleEvent<
50+
TokenOperationType.RemoveDenyList,
51+
TokenListUpdateEventDetails
52+
>;
53+
54+
/**
55+
* An event occuring as the result of a "pause" operation, describing whether execution
56+
* of the associated token operations are paused or not.
57+
*/
58+
export type TokenPauseEvent = GenTokenModuleEvent<TokenOperationType.Pause, TokenPauseEventDetails>;
59+
60+
/**
61+
* An event occuring as the result of a "pause" operation, describing whether execution
62+
* of the associated token operations are paused or not.
63+
*/
64+
export type TokenUnpauseEvent = GenTokenModuleEvent<TokenOperationType.Unpause, TokenPauseEventDetails>;
65+
66+
/**
67+
* A union of all token module events.
68+
*/
69+
export type TokenModuleEvent =
70+
| TokenAddAllowListEvent
71+
| TokenAddDenyListEvent
72+
| TokenRemoveAllowListEvent
73+
| TokenRemoveDenyListEvent
74+
| TokenPauseEvent
75+
| TokenUnpauseEvent;
76+
77+
/**
78+
* Parses a token module event, decoding the details from CBOR format. If the desired outcome is to be able to handle
79+
* arbitrary token events, it's recommended to use {@link Cbor.decode} instead.
80+
*
81+
* @param event - The token module event to parse.
82+
* @returns The parsed token module event with decoded details.
83+
* @throws {Error} If the event cannot be parsed as a token module event.
84+
*
85+
* @example
86+
* try {
87+
* const parsedEvent = parseModuleEvent(encodedEvent);
88+
* switch (parsedEvent.type) {
89+
* // typed details are now available, e.g.:
90+
* case TokenOperationType.AddAllowList: console.log(parsedEvent.details.target);
91+
* ...
92+
* }
93+
* } catch (error) {
94+
* // Fall back to using Cbor.decode
95+
* const decodedDetails = Cbor.decode(encodedEvent.details);
96+
* switch (encodedEvent.type) {
97+
* // do something with the decoded details
98+
* }
99+
* }
100+
*/
101+
export function parseModuleEvent(event: EncodedTokenModuleEvent): TokenModuleEvent {
102+
switch (event.type) {
103+
case TokenOperationType.AddAllowList:
104+
case TokenOperationType.RemoveAllowList:
105+
case TokenOperationType.AddDenyList:
106+
case TokenOperationType.RemoveDenyList:
107+
return { ...event, type: event.type, details: Cbor.decode(event.details, 'TokenListUpdateEventDetails') };
108+
case TokenOperationType.Pause:
109+
case TokenOperationType.Unpause:
110+
return { ...event, type: event.type, details: Cbor.decode(event.details, 'TokenPauseEventDetails') };
111+
default:
112+
throw new Error(`Cannot parse event as token module event: ${event.type}`);
113+
}
114+
}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import { TokenAmount, TokenHolder } from './index.js';
2+
import { EncodedTokenModuleRejectReason } from './types.js';
3+
4+
export enum TokenRejectReasonType {
5+
AddressNotFound = 'addressNotFound',
6+
TokenBalanceInsufficient = 'tokenBalanceInsufficient',
7+
DeserializationFailure = 'deserializationFailure',
8+
UnsupportedOperation = 'unsupportedOperation',
9+
OperationNotPermitted = 'operationNotPermitted',
10+
MintWouldOverflow = 'mintWouldOverflow',
11+
}
12+
13+
type RejectReasonGen<T extends TokenRejectReasonType, D> = Omit<EncodedTokenModuleRejectReason, 'type' | 'details'> & {
14+
/** The type of rejection. */
15+
type: T;
16+
/** Additional details about the rejection. */
17+
details: D;
18+
};
19+
20+
/**
21+
* The details of an "addressNotFound": an account address was not valid.
22+
*/
23+
export type AddressNotFoundDetails = {
24+
/** The index in the list of operations of the failing operation. */
25+
index: number;
26+
/** The address that could not be resolved. */
27+
address: TokenHolder.Type;
28+
};
29+
30+
/**
31+
* An account address was not valid.
32+
*/
33+
export type AddressNotFoundRejectReason = RejectReasonGen<
34+
TokenRejectReasonType.AddressNotFound,
35+
AddressNotFoundDetails
36+
>;
37+
38+
/**
39+
* Details for a reject reason where the account's token balance is insufficient
40+
* for the attempted operation.
41+
*
42+
* See CIS-7: reject-reasons/tokenBalanceInsufficient
43+
*/
44+
export type TokenBalanceInsufficientDetails = {
45+
/** The index in the list of operations of the failing operation. */
46+
index: number;
47+
/** The available balance for the sender at the time of the operation. */
48+
availableBalance: TokenAmount.Type;
49+
/** The minimum required balance to perform the operation. */
50+
requiredBalance: TokenAmount.Type;
51+
};
52+
53+
/** Typed reject reason for "tokenBalanceInsufficient". */
54+
export type TokenBalanceInsufficientRejectReason = RejectReasonGen<
55+
TokenRejectReasonType.TokenBalanceInsufficient,
56+
TokenBalanceInsufficientDetails
57+
>;
58+
59+
/**
60+
* Details for a reject reason where the operation payload could not be deserialized.
61+
*
62+
* See CIS-7: reject-reasons/deserializationFailure
63+
*/
64+
export type DeserializationFailureDetails = {
65+
/** Text description of the failure mode. */
66+
cause?: string;
67+
};
68+
69+
/** Typed reject reason for "deserializationFailure". */
70+
export type DeserializationFailureRejectReason = RejectReasonGen<
71+
TokenRejectReasonType.DeserializationFailure,
72+
DeserializationFailureDetails
73+
>;
74+
75+
/**
76+
* Details for a reject reason where the specified operation is not supported by the module.
77+
*
78+
* See CIS-7: reject-reasons/unsupportedOperation
79+
*/
80+
export type UnsupportedOperationDetails = {
81+
/** The index in the list of operations of the failing operation. */
82+
index: number;
83+
/** The type of operation that was not supported. */
84+
operationType: string;
85+
/** The reason why the operation was not supported. */
86+
reason?: string;
87+
};
88+
89+
/** Typed reject reason for "unsupportedOperation". */
90+
export type UnsupportedOperationRejectReason = RejectReasonGen<
91+
TokenRejectReasonType.UnsupportedOperation,
92+
UnsupportedOperationDetails
93+
>;
94+
95+
/**
96+
* Details for a reject reason where the operation is recognized but not permitted
97+
* under the current state or policy (e.g., paused, allow/deny list).
98+
*
99+
* See CIS-7: reject-reasons/operationNotPermitted
100+
*/
101+
export type OperationNotPermittedDetails = {
102+
/** The index in the list of operations of the failing operation. */
103+
index: number;
104+
/** (Optionally) the address that does not have the necessary permissions to perform the operation. */
105+
address?: TokenHolder.Type;
106+
/** The reason why the operation is not permitted. */
107+
reason?: string;
108+
};
109+
110+
/** Typed reject reason for "operationNotPermitted". */
111+
export type OperationNotPermittedRejectReason = RejectReasonGen<
112+
TokenRejectReasonType.OperationNotPermitted,
113+
OperationNotPermittedDetails
114+
>;
115+
116+
/**
117+
* Details for a reject reason where minting would overflow supply constraints.
118+
*
119+
* See CIS-7: reject-reasons/mintWouldOverflow
120+
*/
121+
export type MintWouldOverflowDetails = {
122+
/** The index in the list of operations of the failing operation. */
123+
index: number;
124+
/** The requested amount to mint. */
125+
requestedAmount: TokenAmount.Type;
126+
/** The current supply of the token. */
127+
currentSupply: TokenAmount.Type;
128+
/** The maximum representable token amount. */
129+
maxRepresentableAmount: TokenAmount.Type;
130+
};
131+
132+
/** Typed reject reason for "mintWouldOverflow". */
133+
export type MintWouldOverflowRejectReason = RejectReasonGen<
134+
TokenRejectReasonType.MintWouldOverflow,
135+
MintWouldOverflowDetails
136+
>;
137+
138+
/**
139+
* Union of all token module reject reasons defined by CIS-7,
140+
* with strongly-typed details per reason.
141+
*
142+
* @see https://proposals.concordium.com/CIS/cis-7.html#reject-reasons
143+
*/
144+
export type TokenModuleRejectReason =
145+
| AddressNotFoundRejectReason
146+
| TokenBalanceInsufficientRejectReason
147+
| DeserializationFailureRejectReason
148+
| UnsupportedOperationRejectReason
149+
| OperationNotPermittedRejectReason
150+
| MintWouldOverflowRejectReason;

0 commit comments

Comments
 (0)