sui
sui copied to clipboard
[RFC][BCS/TS] Support multiple schemas
Currently, bcs
accumulates registered types in a singleton, updated by static functions so it's only possible to have one interface for each type name. This proposal suggests adding the ability to create new instances of the bcs
, each with their own types registered.
Motivation
#4878 introduces a backwards incompatible change to Sui's BCS schema (the addition of a field, deep within the structure of a Move Call Transaction). For backwards compatibility, the TypeScript SDK needs to be able to talk to both the old and new schemas. This was achieved by:
-
Duplicating all the BCS type registrations between
ObjectArg
(the type that changed) andTransactionData
(the root), through 9 type registrations.
https://github.com/MystenLabs/sui/blob/d379a70a37caf4e2acf7b9aa9cfcf6a1a278aa66/sdk/typescript/src/types/sui-bcs.ts#L316-L363
- Supplying a different root type name during serialization, based on the version advertised by the RPC Provider:
https://github.com/MystenLabs/sui/blob/d379a70a37caf4e2acf7b9aa9cfcf6a1a278aa66/sdk/typescript/src/signers/txn-data-serializers/local-txn-data-serializer.ts#L345-L349
But this is quite error-prone and cumbersome, especially if we need to manage multiple unrelated schema changes. Ideally, instead of this approach, we could define multiple schemas (or a function that returns a schema, based on RPC version), so the example above becomes:
// sui-bcs.ts
function bcsSchema(version: string): BCS {
const bcs = new BCS();
/* ... */
if (version === "0.11.0" || version === "0.12.0") {
bcs.registerEnumType('ObjectArg', {
ImmOrOwned: 'SuiObjectRef',
Shared_Deprecated: 'ObjectID',
});
} else {
bcs.registerStructType('SharedObjectRef', {
objectId: 'ObjectID',
initialSharedVersion: 'u64',
});
bcs.registerEnumType('ObjectArg', {
ImmOrOwned: 'SuiObjectRef',
Shared: 'SharedObjectRef',
});
}
/* ... */
return bcs;
}
export function bcsForAPI(version: string): BCS {
/* wrapper to the above, with caching */
}
// local-txn-data-serializer.ts
const dataBytes = bcsForAPI(version).ser('TransactionData', tx, size).toBytes();