common.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { snakeCase } from "snake-case";
  2. import { sha256 } from "js-sha256";
  3. import { Idl, IdlField, IdlTypeDef, IdlEnumVariant, IdlType } from "../idl";
  4. import { IdlError } from "../error";
  5. export function accountSize(
  6. idl: Idl,
  7. idlAccount: IdlTypeDef
  8. ): number | undefined {
  9. if (idlAccount.type.kind === "enum") {
  10. let variantSizes = idlAccount.type.variants.map(
  11. (variant: IdlEnumVariant) => {
  12. if (variant.fields === undefined) {
  13. return 0;
  14. }
  15. return (
  16. variant.fields
  17. // @ts-ignore
  18. .map((f: IdlField | IdlType) => {
  19. // @ts-ignore
  20. if (f.name === undefined) {
  21. throw new Error("Tuple enum variants not yet implemented.");
  22. }
  23. // @ts-ignore
  24. return typeSize(idl, f.type);
  25. })
  26. .reduce((a: number, b: number) => a + b)
  27. );
  28. }
  29. );
  30. return Math.max(...variantSizes) + 1;
  31. }
  32. if (idlAccount.type.fields === undefined) {
  33. return 0;
  34. }
  35. return idlAccount.type.fields
  36. .map((f) => typeSize(idl, f.type))
  37. .reduce((a, b) => a + b);
  38. }
  39. // Returns the size of the type in bytes. For variable length types, just return
  40. // 1. Users should override this value in such cases.
  41. function typeSize(idl: Idl, ty: IdlType): number {
  42. switch (ty) {
  43. case "bool":
  44. return 1;
  45. case "u8":
  46. return 1;
  47. case "i8":
  48. return 1;
  49. case "i16":
  50. return 2;
  51. case "u16":
  52. return 2;
  53. case "u32":
  54. return 4;
  55. case "i32":
  56. return 4;
  57. case "u64":
  58. return 8;
  59. case "i64":
  60. return 8;
  61. case "u128":
  62. return 16;
  63. case "i128":
  64. return 16;
  65. case "bytes":
  66. return 1;
  67. case "string":
  68. return 1;
  69. case "publicKey":
  70. return 32;
  71. default:
  72. // @ts-ignore
  73. if (ty.vec !== undefined) {
  74. return 1;
  75. }
  76. // @ts-ignore
  77. if (ty.option !== undefined) {
  78. // @ts-ignore
  79. return 1 + typeSize(idl, ty.option);
  80. }
  81. // @ts-ignore
  82. if (ty.defined !== undefined) {
  83. // @ts-ignore
  84. const filtered = idl.types.filter((t) => t.name === ty.defined);
  85. if (filtered.length !== 1) {
  86. throw new IdlError(`Type not found: ${JSON.stringify(ty)}`);
  87. }
  88. let typeDef = filtered[0];
  89. return accountSize(idl, typeDef);
  90. }
  91. // @ts-ignore
  92. if (ty.array !== undefined) {
  93. // @ts-ignore
  94. let arrayTy = ty.array[0];
  95. // @ts-ignore
  96. let arraySize = ty.array[1];
  97. // @ts-ignore
  98. return typeSize(idl, arrayTy) * arraySize;
  99. }
  100. throw new Error(`Invalid type ${JSON.stringify(ty)}`);
  101. }
  102. }
  103. // Not technically sighash, since we don't include the arguments, as Rust
  104. // doesn't allow function overloading.
  105. export function sighash(nameSpace: string, ixName: string): Buffer {
  106. let name = snakeCase(ixName);
  107. let preimage = `${nameSpace}:${name}`;
  108. return Buffer.from(sha256.digest(preimage)).slice(0, 8);
  109. }