@peeramid-labs/sdk 3.4.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. package/README.md +5 -5
  2. package/cli/abis/ArguableVotingTournament.js +17 -1
  3. package/cli/abis/ArguableVotingTournament.js.map +1 -1
  4. package/cli/abis/Create2.js +12 -0
  5. package/cli/abis/Create2.js.map +1 -0
  6. package/cli/abis/DiamondDistribution.js +17 -1
  7. package/cli/abis/DiamondDistribution.js.map +1 -1
  8. package/cli/abis/{CodeIndex.js → ERC7744.js} +4 -4
  9. package/cli/abis/ERC7744.js.map +1 -0
  10. package/cli/abis/Errors.js +44 -0
  11. package/cli/abis/Errors.js.map +1 -0
  12. package/{lib.commonjs/abis/CodeIndex.js → cli/abis/IERC7744.js} +4 -4
  13. package/cli/abis/IERC7744.js.map +1 -0
  14. package/cli/abis/IErrors.js +16 -0
  15. package/cli/abis/IErrors.js.map +1 -1
  16. package/cli/abis/IPoseidon2.js +26 -0
  17. package/cli/abis/IPoseidon2.js.map +1 -0
  18. package/cli/abis/IPoseidon5.js +26 -0
  19. package/cli/abis/IPoseidon5.js.map +1 -0
  20. package/cli/abis/IPoseidon6.js +26 -0
  21. package/cli/abis/IPoseidon6.js.map +1 -0
  22. package/cli/abis/IRankifyInstance.js +13 -1
  23. package/cli/abis/IRankifyInstance.js.map +1 -1
  24. package/cli/abis/InitializedDiamondDistribution.js +17 -1
  25. package/cli/abis/InitializedDiamondDistribution.js.map +1 -1
  26. package/cli/abis/MAODistribution.js +22 -1
  27. package/cli/abis/MAODistribution.js.map +1 -1
  28. package/cli/abis/ProposalsIntegrity15Groth16Verifier.js +1120 -0
  29. package/cli/abis/ProposalsIntegrity15Groth16Verifier.js.map +1 -0
  30. package/cli/abis/RankifyDiamondInstance.js +319 -15
  31. package/cli/abis/RankifyDiamondInstance.js.map +1 -1
  32. package/cli/abis/RankifyInstanceEventMock.js +1 -1
  33. package/cli/abis/RankifyInstanceEventMock.js.map +1 -1
  34. package/cli/abis/RankifyInstanceGameMastersFacet.js +132 -13
  35. package/cli/abis/RankifyInstanceGameMastersFacet.js.map +1 -1
  36. package/cli/abis/RankifyInstanceInit.js +20 -0
  37. package/cli/abis/RankifyInstanceInit.js.map +1 -1
  38. package/cli/abis/RankifyInstanceMainFacet.js +121 -2
  39. package/cli/abis/RankifyInstanceMainFacet.js.map +1 -1
  40. package/cli/abis/RankifyInstanceRequirementsFacet.js +25 -0
  41. package/cli/abis/RankifyInstanceRequirementsFacet.js.map +1 -1
  42. package/cli/abis/index.js +35 -11
  43. package/cli/abis/index.js.map +1 -1
  44. package/cli/cli/commands/distributions/add.js +2 -2
  45. package/cli/cli/commands/distributions/add.js.map +1 -1
  46. package/cli/cli/commands/eds/index.js +17 -3
  47. package/cli/cli/commands/eds/index.js.map +1 -1
  48. package/cli/cli/commands/fellowship/create.js +0 -1
  49. package/cli/cli/commands/fellowship/create.js.map +1 -1
  50. package/cli/cli/index.js +2 -0
  51. package/cli/cli/index.js.map +1 -1
  52. package/cli/eds/Distributor.js +4 -5
  53. package/cli/eds/Distributor.js.map +1 -1
  54. package/cli/rankify/InstanceBase.js +103 -42
  55. package/cli/rankify/InstanceBase.js.map +1 -1
  56. package/cli/rankify/MAODistributor.js +19 -2
  57. package/cli/rankify/MAODistributor.js.map +1 -1
  58. package/cli/types.js +22 -1
  59. package/cli/types.js.map +1 -1
  60. package/cli/utils/ApiError.js +2 -1
  61. package/cli/utils/ApiError.js.map +1 -1
  62. package/cli/utils/artifacts.js +18 -0
  63. package/cli/utils/artifacts.js.map +1 -1
  64. package/cli/utils/log.js +26 -0
  65. package/cli/utils/log.js.map +1 -0
  66. package/cli/utils/permutations.js +32 -0
  67. package/cli/utils/permutations.js.map +1 -0
  68. package/docs/classes/GameMaster.md +377 -79
  69. package/docs/classes/InstanceBase.md +125 -14
  70. package/docs/classes/InstancePlayer.md +310 -36
  71. package/docs/docs/classes/GameMaster.md +377 -79
  72. package/docs/docs/classes/InstanceBase.md +125 -14
  73. package/docs/docs/classes/InstancePlayer.md +310 -36
  74. package/docs/docs/index.md +67 -19
  75. package/docs/docs/interfaces/GameMetadata.md +91 -0
  76. package/docs/docs/interfaces/GmProposalParams.md +41 -0
  77. package/docs/docs/interfaces/Submission.md +52 -0
  78. package/docs/index.md +67 -19
  79. package/docs/interfaces/GameMetadata.md +91 -0
  80. package/docs/interfaces/GmProposalParams.md +41 -0
  81. package/docs/interfaces/Submission.md +52 -0
  82. package/lib.commonjs/abis/ArguableVotingTournament.d.ts +13 -1
  83. package/lib.commonjs/abis/ArguableVotingTournament.d.ts.map +1 -1
  84. package/lib.commonjs/abis/ArguableVotingTournament.js +17 -1
  85. package/lib.commonjs/abis/ArguableVotingTournament.js.map +1 -1
  86. package/lib.commonjs/abis/Create2.d.ts +7 -0
  87. package/lib.commonjs/abis/Create2.d.ts.map +1 -0
  88. package/lib.commonjs/abis/Create2.js +12 -0
  89. package/lib.commonjs/abis/Create2.js.map +1 -0
  90. package/lib.commonjs/abis/DiamondDistribution.d.ts +13 -1
  91. package/lib.commonjs/abis/DiamondDistribution.d.ts.map +1 -1
  92. package/lib.commonjs/abis/DiamondDistribution.js +17 -1
  93. package/lib.commonjs/abis/DiamondDistribution.js.map +1 -1
  94. package/lib.commonjs/abis/{CodeIndex.d.ts → ERC7744.d.ts} +3 -3
  95. package/lib.commonjs/abis/ERC7744.d.ts.map +1 -0
  96. package/{cli/abis/ICodeIndex.js → lib.commonjs/abis/ERC7744.js} +4 -4
  97. package/lib.commonjs/abis/ERC7744.js.map +1 -0
  98. package/lib.commonjs/abis/Errors.d.ts +31 -0
  99. package/lib.commonjs/abis/Errors.d.ts.map +1 -0
  100. package/lib.commonjs/abis/Errors.js +44 -0
  101. package/lib.commonjs/abis/Errors.js.map +1 -0
  102. package/{lib.esm/abis/CodeIndex.d.ts → lib.commonjs/abis/IERC7744.d.ts} +3 -3
  103. package/lib.commonjs/abis/IERC7744.d.ts.map +1 -0
  104. package/lib.commonjs/abis/{ICodeIndex.js → IERC7744.js} +4 -4
  105. package/lib.commonjs/abis/IERC7744.js.map +1 -0
  106. package/lib.commonjs/abis/IErrors.d.ts +12 -0
  107. package/lib.commonjs/abis/IErrors.d.ts.map +1 -1
  108. package/lib.commonjs/abis/IErrors.js +16 -0
  109. package/lib.commonjs/abis/IErrors.js.map +1 -1
  110. package/lib.commonjs/abis/IPoseidon2.d.ts +17 -0
  111. package/lib.commonjs/abis/IPoseidon2.d.ts.map +1 -0
  112. package/lib.commonjs/abis/IPoseidon2.js +26 -0
  113. package/lib.commonjs/abis/IPoseidon2.js.map +1 -0
  114. package/lib.commonjs/abis/IPoseidon5.d.ts +17 -0
  115. package/lib.commonjs/abis/IPoseidon5.d.ts.map +1 -0
  116. package/lib.commonjs/abis/IPoseidon5.js +26 -0
  117. package/lib.commonjs/abis/IPoseidon5.js.map +1 -0
  118. package/lib.commonjs/abis/IPoseidon6.d.ts +17 -0
  119. package/lib.commonjs/abis/IPoseidon6.d.ts.map +1 -0
  120. package/lib.commonjs/abis/IPoseidon6.js +26 -0
  121. package/lib.commonjs/abis/IPoseidon6.js.map +1 -0
  122. package/lib.commonjs/abis/IRankifyInstance.d.ts +11 -1
  123. package/lib.commonjs/abis/IRankifyInstance.d.ts.map +1 -1
  124. package/lib.commonjs/abis/IRankifyInstance.js +13 -1
  125. package/lib.commonjs/abis/IRankifyInstance.js.map +1 -1
  126. package/lib.commonjs/abis/InitializedDiamondDistribution.d.ts +13 -1
  127. package/lib.commonjs/abis/InitializedDiamondDistribution.d.ts.map +1 -1
  128. package/lib.commonjs/abis/InitializedDiamondDistribution.js +17 -1
  129. package/lib.commonjs/abis/InitializedDiamondDistribution.js.map +1 -1
  130. package/lib.commonjs/abis/MAODistribution.d.ts +17 -1
  131. package/lib.commonjs/abis/MAODistribution.d.ts.map +1 -1
  132. package/lib.commonjs/abis/MAODistribution.js +22 -1
  133. package/lib.commonjs/abis/MAODistribution.js.map +1 -1
  134. package/lib.commonjs/abis/ProposalsIntegrity15Groth16Verifier.d.ts +859 -0
  135. package/lib.commonjs/abis/ProposalsIntegrity15Groth16Verifier.d.ts.map +1 -0
  136. package/lib.commonjs/abis/ProposalsIntegrity15Groth16Verifier.js +1120 -0
  137. package/lib.commonjs/abis/ProposalsIntegrity15Groth16Verifier.js.map +1 -0
  138. package/lib.commonjs/abis/RankifyDiamondInstance.d.ts +251 -15
  139. package/lib.commonjs/abis/RankifyDiamondInstance.d.ts.map +1 -1
  140. package/lib.commonjs/abis/RankifyDiamondInstance.js +319 -15
  141. package/lib.commonjs/abis/RankifyDiamondInstance.js.map +1 -1
  142. package/lib.commonjs/abis/RankifyInstanceEventMock.d.ts +1 -1
  143. package/lib.commonjs/abis/RankifyInstanceEventMock.js +1 -1
  144. package/lib.commonjs/abis/RankifyInstanceEventMock.js.map +1 -1
  145. package/lib.commonjs/abis/RankifyInstanceGameMastersFacet.d.ts +107 -13
  146. package/lib.commonjs/abis/RankifyInstanceGameMastersFacet.d.ts.map +1 -1
  147. package/lib.commonjs/abis/RankifyInstanceGameMastersFacet.js +132 -13
  148. package/lib.commonjs/abis/RankifyInstanceGameMastersFacet.js.map +1 -1
  149. package/lib.commonjs/abis/RankifyInstanceInit.d.ts +16 -0
  150. package/lib.commonjs/abis/RankifyInstanceInit.d.ts.map +1 -1
  151. package/lib.commonjs/abis/RankifyInstanceInit.js +20 -0
  152. package/lib.commonjs/abis/RankifyInstanceInit.js.map +1 -1
  153. package/lib.commonjs/abis/RankifyInstanceMainFacet.d.ts +94 -2
  154. package/lib.commonjs/abis/RankifyInstanceMainFacet.d.ts.map +1 -1
  155. package/lib.commonjs/abis/RankifyInstanceMainFacet.js +121 -2
  156. package/lib.commonjs/abis/RankifyInstanceMainFacet.js.map +1 -1
  157. package/lib.commonjs/abis/RankifyInstanceRequirementsFacet.d.ts +20 -0
  158. package/lib.commonjs/abis/RankifyInstanceRequirementsFacet.d.ts.map +1 -1
  159. package/lib.commonjs/abis/RankifyInstanceRequirementsFacet.js +25 -0
  160. package/lib.commonjs/abis/RankifyInstanceRequirementsFacet.js.map +1 -1
  161. package/lib.commonjs/abis/index.d.ts +1699 -225
  162. package/lib.commonjs/abis/index.d.ts.map +1 -1
  163. package/lib.commonjs/abis/index.js +35 -11
  164. package/lib.commonjs/abis/index.js.map +1 -1
  165. package/lib.commonjs/eds/Distributor.d.ts.map +1 -1
  166. package/lib.commonjs/eds/Distributor.js +4 -5
  167. package/lib.commonjs/eds/Distributor.js.map +1 -1
  168. package/lib.commonjs/index.d.ts +1 -2
  169. package/lib.commonjs/index.d.ts.map +1 -1
  170. package/lib.commonjs/index.js +1 -4
  171. package/lib.commonjs/index.js.map +1 -1
  172. package/lib.commonjs/rankify/GameMaster.d.ts +289 -43
  173. package/lib.commonjs/rankify/GameMaster.d.ts.map +1 -1
  174. package/lib.commonjs/rankify/GameMaster.js +794 -122
  175. package/lib.commonjs/rankify/GameMaster.js.map +1 -1
  176. package/lib.commonjs/rankify/InstanceBase.d.ts +1392 -3454
  177. package/lib.commonjs/rankify/InstanceBase.d.ts.map +1 -1
  178. package/lib.commonjs/rankify/InstanceBase.js +103 -42
  179. package/lib.commonjs/rankify/InstanceBase.js.map +1 -1
  180. package/lib.commonjs/rankify/MAODistributor.d.ts.map +1 -1
  181. package/lib.commonjs/rankify/MAODistributor.js +19 -2
  182. package/lib.commonjs/rankify/MAODistributor.js.map +1 -1
  183. package/lib.commonjs/rankify/Player.d.ts +80 -2
  184. package/lib.commonjs/rankify/Player.d.ts.map +1 -1
  185. package/lib.commonjs/rankify/Player.js +138 -4
  186. package/lib.commonjs/rankify/Player.js.map +1 -1
  187. package/lib.commonjs/types/contracts.d.ts +18 -0
  188. package/lib.commonjs/types/contracts.d.ts.map +1 -1
  189. package/lib.commonjs/types.d.ts +68 -6
  190. package/lib.commonjs/types.d.ts.map +1 -1
  191. package/lib.commonjs/types.js +22 -1
  192. package/lib.commonjs/types.js.map +1 -1
  193. package/lib.commonjs/utils/ApiError.d.ts.map +1 -1
  194. package/lib.commonjs/utils/ApiError.js +2 -1
  195. package/lib.commonjs/utils/ApiError.js.map +1 -1
  196. package/lib.commonjs/utils/artifacts.d.ts +5 -3
  197. package/lib.commonjs/utils/artifacts.d.ts.map +1 -1
  198. package/lib.commonjs/utils/artifacts.js +18 -0
  199. package/lib.commonjs/utils/artifacts.js.map +1 -1
  200. package/lib.commonjs/utils/getEnv.d.ts +9 -0
  201. package/lib.commonjs/utils/getEnv.d.ts.map +1 -0
  202. package/lib.commonjs/utils/getEnv.js +18 -0
  203. package/lib.commonjs/utils/getEnv.js.map +1 -0
  204. package/lib.commonjs/utils/log.d.ts +2 -0
  205. package/lib.commonjs/utils/log.d.ts.map +1 -0
  206. package/lib.commonjs/utils/log.js +26 -0
  207. package/lib.commonjs/utils/log.js.map +1 -0
  208. package/lib.commonjs/utils/permutations.d.ts +21 -0
  209. package/lib.commonjs/utils/permutations.d.ts.map +1 -0
  210. package/lib.commonjs/utils/permutations.js +32 -0
  211. package/lib.commonjs/utils/permutations.js.map +1 -0
  212. package/lib.esm/abis/ArguableVotingTournament.d.ts +13 -1
  213. package/lib.esm/abis/ArguableVotingTournament.d.ts.map +1 -1
  214. package/lib.esm/abis/ArguableVotingTournament.js +17 -1
  215. package/lib.esm/abis/ArguableVotingTournament.js.map +1 -1
  216. package/lib.esm/abis/Create2.d.ts +7 -0
  217. package/lib.esm/abis/Create2.d.ts.map +1 -0
  218. package/lib.esm/abis/Create2.js +9 -0
  219. package/lib.esm/abis/Create2.js.map +1 -0
  220. package/lib.esm/abis/DiamondDistribution.d.ts +13 -1
  221. package/lib.esm/abis/DiamondDistribution.d.ts.map +1 -1
  222. package/lib.esm/abis/DiamondDistribution.js +17 -1
  223. package/lib.esm/abis/DiamondDistribution.js.map +1 -1
  224. package/{lib.commonjs/abis/ICodeIndex.d.ts → lib.esm/abis/ERC7744.d.ts} +3 -3
  225. package/lib.esm/abis/ERC7744.d.ts.map +1 -0
  226. package/lib.esm/abis/{CodeIndex.js → ERC7744.js} +3 -3
  227. package/lib.esm/abis/ERC7744.js.map +1 -0
  228. package/lib.esm/abis/Errors.d.ts +31 -0
  229. package/lib.esm/abis/Errors.d.ts.map +1 -0
  230. package/lib.esm/abis/Errors.js +41 -0
  231. package/lib.esm/abis/Errors.js.map +1 -0
  232. package/lib.esm/abis/{ICodeIndex.d.ts → IERC7744.d.ts} +3 -3
  233. package/lib.esm/abis/IERC7744.d.ts.map +1 -0
  234. package/lib.esm/abis/{ICodeIndex.js → IERC7744.js} +3 -3
  235. package/lib.esm/abis/IERC7744.js.map +1 -0
  236. package/lib.esm/abis/IErrors.d.ts +12 -0
  237. package/lib.esm/abis/IErrors.d.ts.map +1 -1
  238. package/lib.esm/abis/IErrors.js +16 -0
  239. package/lib.esm/abis/IErrors.js.map +1 -1
  240. package/lib.esm/abis/IPoseidon2.d.ts +17 -0
  241. package/lib.esm/abis/IPoseidon2.d.ts.map +1 -0
  242. package/lib.esm/abis/IPoseidon2.js +23 -0
  243. package/lib.esm/abis/IPoseidon2.js.map +1 -0
  244. package/lib.esm/abis/IPoseidon5.d.ts +17 -0
  245. package/lib.esm/abis/IPoseidon5.d.ts.map +1 -0
  246. package/lib.esm/abis/IPoseidon5.js +23 -0
  247. package/lib.esm/abis/IPoseidon5.js.map +1 -0
  248. package/lib.esm/abis/IPoseidon6.d.ts +17 -0
  249. package/lib.esm/abis/IPoseidon6.d.ts.map +1 -0
  250. package/lib.esm/abis/IPoseidon6.js +23 -0
  251. package/lib.esm/abis/IPoseidon6.js.map +1 -0
  252. package/lib.esm/abis/IRankifyInstance.d.ts +11 -1
  253. package/lib.esm/abis/IRankifyInstance.d.ts.map +1 -1
  254. package/lib.esm/abis/IRankifyInstance.js +13 -1
  255. package/lib.esm/abis/IRankifyInstance.js.map +1 -1
  256. package/lib.esm/abis/InitializedDiamondDistribution.d.ts +13 -1
  257. package/lib.esm/abis/InitializedDiamondDistribution.d.ts.map +1 -1
  258. package/lib.esm/abis/InitializedDiamondDistribution.js +17 -1
  259. package/lib.esm/abis/InitializedDiamondDistribution.js.map +1 -1
  260. package/lib.esm/abis/MAODistribution.d.ts +17 -1
  261. package/lib.esm/abis/MAODistribution.d.ts.map +1 -1
  262. package/lib.esm/abis/MAODistribution.js +22 -1
  263. package/lib.esm/abis/MAODistribution.js.map +1 -1
  264. package/lib.esm/abis/ProposalsIntegrity15Groth16Verifier.d.ts +859 -0
  265. package/lib.esm/abis/ProposalsIntegrity15Groth16Verifier.d.ts.map +1 -0
  266. package/lib.esm/abis/ProposalsIntegrity15Groth16Verifier.js +1117 -0
  267. package/lib.esm/abis/ProposalsIntegrity15Groth16Verifier.js.map +1 -0
  268. package/lib.esm/abis/RankifyDiamondInstance.d.ts +251 -15
  269. package/lib.esm/abis/RankifyDiamondInstance.d.ts.map +1 -1
  270. package/lib.esm/abis/RankifyDiamondInstance.js +319 -15
  271. package/lib.esm/abis/RankifyDiamondInstance.js.map +1 -1
  272. package/lib.esm/abis/RankifyInstanceEventMock.d.ts +1 -1
  273. package/lib.esm/abis/RankifyInstanceEventMock.js +1 -1
  274. package/lib.esm/abis/RankifyInstanceEventMock.js.map +1 -1
  275. package/lib.esm/abis/RankifyInstanceGameMastersFacet.d.ts +107 -13
  276. package/lib.esm/abis/RankifyInstanceGameMastersFacet.d.ts.map +1 -1
  277. package/lib.esm/abis/RankifyInstanceGameMastersFacet.js +132 -13
  278. package/lib.esm/abis/RankifyInstanceGameMastersFacet.js.map +1 -1
  279. package/lib.esm/abis/RankifyInstanceInit.d.ts +16 -0
  280. package/lib.esm/abis/RankifyInstanceInit.d.ts.map +1 -1
  281. package/lib.esm/abis/RankifyInstanceInit.js +20 -0
  282. package/lib.esm/abis/RankifyInstanceInit.js.map +1 -1
  283. package/lib.esm/abis/RankifyInstanceMainFacet.d.ts +94 -2
  284. package/lib.esm/abis/RankifyInstanceMainFacet.d.ts.map +1 -1
  285. package/lib.esm/abis/RankifyInstanceMainFacet.js +121 -2
  286. package/lib.esm/abis/RankifyInstanceMainFacet.js.map +1 -1
  287. package/lib.esm/abis/RankifyInstanceRequirementsFacet.d.ts +20 -0
  288. package/lib.esm/abis/RankifyInstanceRequirementsFacet.d.ts.map +1 -1
  289. package/lib.esm/abis/RankifyInstanceRequirementsFacet.js +25 -0
  290. package/lib.esm/abis/RankifyInstanceRequirementsFacet.js.map +1 -1
  291. package/lib.esm/abis/index.d.ts +1699 -225
  292. package/lib.esm/abis/index.d.ts.map +1 -1
  293. package/lib.esm/abis/index.js +24 -6
  294. package/lib.esm/abis/index.js.map +1 -1
  295. package/lib.esm/eds/Distributor.d.ts.map +1 -1
  296. package/lib.esm/eds/Distributor.js +4 -5
  297. package/lib.esm/eds/Distributor.js.map +1 -1
  298. package/lib.esm/index.d.ts +1 -2
  299. package/lib.esm/index.d.ts.map +1 -1
  300. package/lib.esm/index.js +0 -2
  301. package/lib.esm/index.js.map +1 -1
  302. package/lib.esm/rankify/GameMaster.d.ts +289 -43
  303. package/lib.esm/rankify/GameMaster.d.ts.map +1 -1
  304. package/lib.esm/rankify/GameMaster.js +795 -123
  305. package/lib.esm/rankify/GameMaster.js.map +1 -1
  306. package/lib.esm/rankify/InstanceBase.d.ts +1392 -3454
  307. package/lib.esm/rankify/InstanceBase.d.ts.map +1 -1
  308. package/lib.esm/rankify/InstanceBase.js +89 -27
  309. package/lib.esm/rankify/InstanceBase.js.map +1 -1
  310. package/lib.esm/rankify/MAODistributor.d.ts.map +1 -1
  311. package/lib.esm/rankify/MAODistributor.js +20 -3
  312. package/lib.esm/rankify/MAODistributor.js.map +1 -1
  313. package/lib.esm/rankify/Player.d.ts +80 -2
  314. package/lib.esm/rankify/Player.d.ts.map +1 -1
  315. package/lib.esm/rankify/Player.js +138 -4
  316. package/lib.esm/rankify/Player.js.map +1 -1
  317. package/lib.esm/types/contracts.d.ts +18 -0
  318. package/lib.esm/types/contracts.d.ts.map +1 -1
  319. package/lib.esm/types.d.ts +68 -6
  320. package/lib.esm/types.d.ts.map +1 -1
  321. package/lib.esm/types.js +21 -0
  322. package/lib.esm/types.js.map +1 -1
  323. package/lib.esm/utils/ApiError.d.ts.map +1 -1
  324. package/lib.esm/utils/ApiError.js +2 -1
  325. package/lib.esm/utils/ApiError.js.map +1 -1
  326. package/lib.esm/utils/artifacts.d.ts +5 -3
  327. package/lib.esm/utils/artifacts.d.ts.map +1 -1
  328. package/lib.esm/utils/artifacts.js +18 -0
  329. package/lib.esm/utils/artifacts.js.map +1 -1
  330. package/lib.esm/utils/getEnv.d.ts +9 -0
  331. package/lib.esm/utils/getEnv.d.ts.map +1 -0
  332. package/lib.esm/utils/getEnv.js +15 -0
  333. package/lib.esm/utils/getEnv.js.map +1 -0
  334. package/lib.esm/utils/log.d.ts +2 -0
  335. package/lib.esm/utils/log.d.ts.map +1 -0
  336. package/lib.esm/utils/log.js +20 -0
  337. package/lib.esm/utils/log.js.map +1 -0
  338. package/lib.esm/utils/permutations.d.ts +21 -0
  339. package/lib.esm/utils/permutations.d.ts.map +1 -0
  340. package/lib.esm/utils/permutations.js +27 -0
  341. package/lib.esm/utils/permutations.js.map +1 -0
  342. package/package.json +17 -10
  343. package/cli/abis/CodeIndex.js.map +0 -1
  344. package/cli/abis/ICodeIndex.js.map +0 -1
  345. package/lib.commonjs/abis/CodeIndex.d.ts.map +0 -1
  346. package/lib.commonjs/abis/CodeIndex.js.map +0 -1
  347. package/lib.commonjs/abis/ICodeIndex.d.ts.map +0 -1
  348. package/lib.commonjs/abis/ICodeIndex.js.map +0 -1
  349. package/lib.esm/abis/CodeIndex.d.ts.map +0 -1
  350. package/lib.esm/abis/CodeIndex.js.map +0 -1
  351. package/lib.esm/abis/ICodeIndex.d.ts.map +0 -1
  352. package/lib.esm/abis/ICodeIndex.js.map +0 -1
@@ -1,7 +1,16 @@
1
- import { keccak256, encodePacked } from "viem";
1
+ import { keccak256, encodePacked, stringToHex, zeroHash, } from "viem";
2
2
  import { RankifyDiamondInstanceAbi } from "../abis";
3
3
  import InstanceBase from "./InstanceBase";
4
+ import { gameStatusEnum } from "../types";
4
5
  import { handleRPCError } from "../utils";
6
+ import { publicKeyToAddress } from "viem/accounts";
7
+ import { logger } from "../utils/log";
8
+ import { buildPoseidon } from "circomlibjs";
9
+ import aes from "crypto-js/aes";
10
+ import cryptoJs from "crypto-js";
11
+ import { CircuitZKit, Groth16Implementer } from "@solarity/zkit";
12
+ import path from "path";
13
+ import { permuteArray, reversePermutation } from "../utils/permutations";
5
14
  /**
6
15
  * GameMaster class for managing game state and cryptographic operations in Rankify
7
16
  * Extends InstanceBase to provide game master specific functionality
@@ -10,10 +19,6 @@ import { handleRPCError } from "../utils";
10
19
  export class GameMaster {
11
20
  walletClient;
12
21
  publicClient;
13
- encryptionCallback;
14
- decryptionCallback;
15
- randomnessCallback;
16
- turnSaltCallback;
17
22
  chainId;
18
23
  /**
19
24
  * Creates a new GameMaster instance
@@ -21,20 +26,41 @@ export class GameMaster {
21
26
  * @param walletClient - Viem wallet client for transactions
22
27
  * @param publicClient - Viem public client for reading state
23
28
  * @param chainId - Chain ID of the network
24
- * @param encryptionCallback - Callback function for encrypting data
25
- * @param decryptionCallback - Callback function for decrypting data
26
- * @param randomnessCallback - Callback function for generating random numbers
27
- * @param turnSaltCallback - Callback function for generating turn salts
28
29
  */
29
- constructor({ walletClient, chainId, publicClient, encryptionCallback, decryptionCallback, randomnessCallback, turnSaltCallback, }) {
30
+ constructor({ walletClient, chainId, publicClient, }) {
30
31
  this.chainId = chainId;
31
32
  this.publicClient = publicClient;
32
33
  this.walletClient = walletClient;
33
- this.encryptionCallback = encryptionCallback;
34
- this.decryptionCallback = decryptionCallback;
35
- this.randomnessCallback = randomnessCallback;
36
- this.turnSaltCallback = turnSaltCallback;
37
34
  }
35
+ /**
36
+ * Decrypts a proposal for a specific game turn
37
+ * @param proposal - The encrypted proposal
38
+ * @param turn - The turn number
39
+ * @param instanceAddress - The address of the instance
40
+ * @param gameId - The ID of the game
41
+ * @param proposer - The address of the proposer
42
+ * @returns The decrypted proposal
43
+ */
44
+ decryptProposal = async ({ proposal, turn, instanceAddress, gameId, proposer, instance, }) => {
45
+ const _instance = instance ?? new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
46
+ const proposerPubKey = await _instance.getPlayerPubKey({
47
+ instanceAddress,
48
+ gameId,
49
+ player: proposer,
50
+ });
51
+ const sharedKey = _instance.sharedSigner({
52
+ publicKey: proposerPubKey,
53
+ privateKey: await this.gameKey({ gameId, contractAddress: instanceAddress }),
54
+ gameId,
55
+ turn,
56
+ contractAddress: instanceAddress,
57
+ chainId: this.chainId,
58
+ });
59
+ logger(`Decrypting proposal ${proposal} with shared key (hashed value: ${keccak256(sharedKey)})`);
60
+ const decryptedProposal = aes.decrypt(proposal, sharedKey).toString(cryptoJs.enc.Utf8);
61
+ logger(`Decrypted proposal ${decryptedProposal}`);
62
+ return decryptedProposal;
63
+ };
38
64
  /**
39
65
  * Decrypts proposals for a specific game turn
40
66
  * @param gameId - ID of the game
@@ -48,55 +74,201 @@ export class GameMaster {
48
74
  address: instanceAddress,
49
75
  eventName: "ProposalSubmitted",
50
76
  args: { gameId: gameId, turn: turn, proposer: proposer },
77
+ fromBlock: 0n,
51
78
  });
79
+ const instance = new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
52
80
  if (evts.length == 0)
53
81
  return [];
82
+ logger(`Decrypting ${evts.length} proposals`);
54
83
  const proposals = await Promise.all(evts.map(async (log) => {
55
- if (!log.args.proposalEncryptedByGM)
84
+ logger(`Decrypting proposal ${log.args.proposer}`);
85
+ if (!log.args.proposer)
86
+ throw new Error("No proposer");
87
+ if (!log.args.encryptedProposal)
56
88
  throw new Error("No proposalEncryptedByGM");
57
89
  return {
58
90
  proposer: log.args.proposer,
59
- proposal: await this.decryptionCallback(log.args.proposalEncryptedByGM),
91
+ proposal: await this.decryptProposal({
92
+ proposal: log.args.encryptedProposal,
93
+ turn: turn,
94
+ instanceAddress: instanceAddress,
95
+ gameId: gameId,
96
+ proposer: log.args.proposer,
97
+ instance,
98
+ }),
60
99
  };
61
100
  }));
62
101
  return proposals;
63
102
  };
64
103
  /**
65
- * Shuffles an array using cryptographically secure randomness
66
- * @param array - Array to shuffle
67
- * @returns Shuffled array
104
+ * Generates a deterministic permutation for a specific game turn
105
+ * @param gameId - ID of the game
106
+ * @param turn - Turn number
107
+ * @param size - Size of the permutation
108
+ * @param verifierAddress - Address of the verifier
109
+ * @returns The generated permutation, secret, and commitment
68
110
  */
69
- shuffle = async (array) => {
70
- const randomness = await this.randomnessCallback();
71
- let currentIndex = array.length, randomIndex;
72
- // While there remain elements to shuffle.
73
- while (currentIndex > 0) {
74
- // Pick a remaining element.
75
- randomIndex = Math.floor(randomness * currentIndex);
76
- currentIndex--;
77
- // And swap it with the current element.
78
- [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]];
111
+ getPermutation = async ({ gameId, turn, size, verifierAddress, }) => {
112
+ const maxSize = 15;
113
+ const turnSalt = await this.getTurnSalt({ gameId, turn, verifierAddress });
114
+ // Create deterministic seed from game parameters and GM's signature
115
+ // Use the seed to generate permutation
116
+ const permutation = Array.from({ length: maxSize }, (_, i) => i);
117
+ // Fisher-Yates shuffle with deterministic randomness
118
+ for (let i = size - 1; i >= 0; i--) {
119
+ // Generate deterministic random number for this position
120
+ const randHash = keccak256(encodePacked(["uint256", "uint256"], [turnSalt, BigInt(i)]));
121
+ const rand = BigInt(randHash);
122
+ const j = Number(rand % BigInt(i + 1));
123
+ // Swap elements
124
+ [permutation[i], permutation[j]] = [permutation[j], permutation[i]];
125
+ }
126
+ // Ensure inactive slots map to themselves
127
+ for (let i = size; i < maxSize; i++) {
128
+ permutation[i] = i;
79
129
  }
80
- return array;
130
+ return { permutation, turnSalt };
131
+ };
132
+ /**
133
+ * Generates a deterministic permutation for a specific game turn
134
+ * @param gameId - ID of the game
135
+ * @param turn - Turn number
136
+ * @param size - Size of the permutation
137
+ * @param verifierAddress - Address of the verifier
138
+ * @returns The generated permutation, secret, and commitment
139
+ */
140
+ generateDeterministicPermutation = async ({ gameId, turn, size = 15, verifierAddress, }) => {
141
+ // This is kept secret to generate witness
142
+ // Create deterministic seed from game parameters and GM's signature
143
+ const { permutation, turnSalt } = await this.getPermutation({ gameId, turn, size, verifierAddress });
144
+ // Generate commitment
145
+ const poseidon = await buildPoseidon();
146
+ const PoseidonFirst = BigInt(poseidon.F.toObject(poseidon([permutation[0], permutation[1], permutation[2], permutation[3], permutation[4]])));
147
+ const PoseidonSecond = BigInt(poseidon.F.toObject(poseidon([PoseidonFirst, permutation[5], permutation[6], permutation[7], permutation[8], permutation[9]])));
148
+ const PoseidonThird = BigInt(poseidon.F.toObject(poseidon([PoseidonSecond, permutation[10], permutation[11], permutation[12], permutation[13], permutation[14]])));
149
+ const commitment = BigInt(poseidon.F.toObject(poseidon([PoseidonThird, turnSalt])));
150
+ return {
151
+ permutation,
152
+ secret: turnSalt,
153
+ commitment,
154
+ };
155
+ };
156
+ /**
157
+ * Permutes an array based on a deterministic permutation
158
+ * @param array - Array to permute
159
+ * @param gameId - ID of the game
160
+ * @param turn - Turn number
161
+ * @param verifierAddress - Address of the verifier
162
+ * @returns The permuted array
163
+ */
164
+ permuteArray = async ({ array, gameId, turn, verifierAddress, }) => {
165
+ const { permutation } = await this.getPermutation({ gameId, turn, size: array.length, verifierAddress });
166
+ return permuteArray({ array, permutation });
167
+ };
168
+ /**
169
+ * Reverses a permutation of an array
170
+ * @param permutedArray - Array to reverse
171
+ * @param gameId - ID of the game
172
+ * @param turn - Turn number
173
+ * @param verifierAddress - Address of the verifier
174
+ * @returns The original array
175
+ */
176
+ reversePermutation = async ({ permutedArray, gameId, turn, verifierAddress, }) => {
177
+ const { permutation } = await this.getPermutation({ gameId, turn, size: permutedArray.length, verifierAddress });
178
+ return reversePermutation({ array: permutedArray, permutation });
81
179
  };
82
180
  /**
83
181
  * Generates a salt for a specific game turn
84
182
  * @param gameId - ID of the game
85
183
  * @param turn - Turn number
184
+ * @param verifierAddress - Address of the verifier
86
185
  * @returns Generated salt as Hex
87
186
  */
88
- getTurnSalt = async ({ gameId, turn }) => {
89
- return this.turnSaltCallback({ gameId, turn }).then((salt) => keccak256(encodePacked(["bytes32", "uint256", "uint256"], [salt, gameId, turn])));
187
+ getTurnSalt = async ({ gameId, turn, verifierAddress, }) => {
188
+ const gameKey = await this.gameKey({ gameId, contractAddress: verifierAddress });
189
+ const instance = new InstanceBase({
190
+ instanceAddress: verifierAddress,
191
+ publicClient: this.publicClient,
192
+ chainId: this.chainId,
193
+ });
194
+ const seed = instance.pkdf({
195
+ privateKey: gameKey,
196
+ turn,
197
+ gameId,
198
+ contractAddress: verifierAddress,
199
+ chainId: this.chainId,
200
+ scope: "turnSalt",
201
+ });
202
+ return BigInt(seed);
90
203
  };
91
204
  /**
92
205
  * Generates a salt for a specific player in a game turn
93
206
  * @param gameId - ID of the game
94
207
  * @param turn - Turn number
95
- * @param proposer - Address of the proposer
208
+ * @param player - Address of the player
209
+ * @param verifierAddress - Address of the verifier
210
+ * @param size - Size of the permutation
96
211
  * @returns Generated salt as Hex
97
212
  */
98
- getTurnPlayersSalt = async ({ gameId, turn, proposer }) => {
99
- return this.getTurnSalt({ gameId, turn }).then((salt) => keccak256(encodePacked(["address", "bytes32"], [proposer, salt])));
213
+ getTurnPlayersSalt = async ({ gameId, turn, player, verifierAddress, size, }) => {
214
+ logger(`Generating vote salt for player ${player} in game ${gameId}, turn ${turn}`);
215
+ const result = await this.generateDeterministicPermutation({
216
+ gameId,
217
+ turn: turn - 1n,
218
+ verifierAddress,
219
+ size,
220
+ }).then((perm) => {
221
+ return keccak256(encodePacked(["address", "uint256"], [player, perm.secret]));
222
+ });
223
+ logger(`Generated vote salt for player ${player}`);
224
+ return result;
225
+ };
226
+ getProposalsVotedUpon = async ({ instanceAddress, gameId, turn, }) => {
227
+ const oldProposals = [];
228
+ //Proposals sequence is directly corresponding to proposers sequence
229
+ if (turn != 1n) {
230
+ const endedEvents = await this.publicClient.getContractEvents({
231
+ address: instanceAddress,
232
+ abi: RankifyDiamondInstanceAbi,
233
+ eventName: "TurnEnded",
234
+ args: { gameId, turn: turn - 1n },
235
+ fromBlock: 0n,
236
+ });
237
+ const evt = endedEvents[0];
238
+ if (endedEvents.length > 1)
239
+ throw new Error("Multiple turns ended");
240
+ const args = evt.args;
241
+ const decryptedProposals = await this.decryptProposals({ instanceAddress, gameId, turn: turn - 1n });
242
+ if (args.newProposals) {
243
+ args.newProposals.slice(0, args?.players?.length).forEach((proposal, idx) => {
244
+ if (proposal !== "") {
245
+ const proposer = decryptedProposals.find((p) => p.proposal === proposal)?.proposer;
246
+ if (!proposer)
247
+ throw new Error("No proposer found for proposal");
248
+ oldProposals[idx] = {
249
+ proposer,
250
+ proposal: proposal,
251
+ };
252
+ }
253
+ });
254
+ }
255
+ else {
256
+ const _players = await this.publicClient.readContract({
257
+ address: instanceAddress,
258
+ abi: RankifyDiamondInstanceAbi,
259
+ functionName: "getPlayers",
260
+ args: [gameId],
261
+ });
262
+ // Boundary case if no-one proposed a thing
263
+ _players.forEach((p, idx) => {
264
+ oldProposals[idx] = {
265
+ proposer: p,
266
+ proposal: "",
267
+ };
268
+ });
269
+ }
270
+ }
271
+ return oldProposals;
100
272
  };
101
273
  /**
102
274
  * Finds the index of a player's ongoing proposal
@@ -104,16 +276,113 @@ export class GameMaster {
104
276
  * @param player - Address of the player
105
277
  * @returns Index of the player's proposal, -1 if not found
106
278
  */
107
- findPlayerOngoingProposalIndex = async ({ instanceAddress, gameId, player, }) => {
279
+ findPlayerOngoingProposalIndex = async ({ instanceAddress, gameId, player, turn, }) => {
108
280
  const baseInstance = new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
109
- const { currentTurn, proposals } = await baseInstance.getOngoingProposals(gameId);
110
- if (currentTurn == 0n) {
111
- console.error("No proposals in turn 0");
112
- return -1;
281
+ let currentTurn = 0n;
282
+ if (!turn) {
283
+ const r = await baseInstance.getOngoingProposals(gameId);
284
+ currentTurn = r.currentTurn;
285
+ if (currentTurn == 0n) {
286
+ console.error("No proposals in turn 0");
287
+ return -1;
288
+ }
289
+ }
290
+ else {
291
+ currentTurn = turn;
113
292
  }
114
- const turn = currentTurn - 1n;
115
- const playersProposal = await this.decryptProposals({ instanceAddress, gameId, turn, proposer: player }).then((ps) => (ps.length > 0 ? ps[0].proposal : undefined));
116
- return playersProposal ? proposals.findIndex((p) => p === playersProposal) : -1;
293
+ const proposalsVotedUpon = await this.getProposalsVotedUpon({ instanceAddress, gameId, turn: currentTurn });
294
+ return proposalsVotedUpon.findIndex((p) => p.proposer === player);
295
+ };
296
+ validateJoinGame = async (props) => {
297
+ const { gameId, participant, instanceAddress } = props;
298
+ try {
299
+ const baseInstance = new InstanceBase({
300
+ instanceAddress,
301
+ publicClient: this.publicClient,
302
+ chainId: this.chainId,
303
+ });
304
+ const gameState = await baseInstance.getGameStateDetails(gameId);
305
+ if (gameState.gamePhase !== gameStatusEnum.open) {
306
+ return { result: false, errorMessage: "Game is not open for registration" };
307
+ }
308
+ if (gameState.players.length === Number(gameState.maxPlayerCnt)) {
309
+ return { result: false, errorMessage: "Game is already full" };
310
+ }
311
+ if (gameState.players.indexOf(participant) !== -1) {
312
+ return { result: false, errorMessage: "Player already registered" };
313
+ }
314
+ return { result: true, errorMessage: "" };
315
+ }
316
+ catch (e) {
317
+ throw await handleRPCError(e);
318
+ }
319
+ };
320
+ /**
321
+ * Signs a joining game event
322
+ * @param gameId - ID of the game
323
+ * @param participant - Address of the participant
324
+ * @param instanceAddress - Address of the game instance
325
+ * @returns Signature and gmCommitment
326
+ */
327
+ signJoiningGame = async (props, timeToJoin = 60 * 10) => {
328
+ if (!this.walletClient.account)
329
+ throw new Error("No account");
330
+ logger(`Signing joining game..`);
331
+ const { gameId, participant, instanceAddress, participantPubKeyHash } = props;
332
+ const baseInstance = new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
333
+ const eip712 = await baseInstance.getEIP712Domain();
334
+ logger({
335
+ gameId: props.gameId,
336
+ participant: props.participant,
337
+ instanceAddress: props.instanceAddress,
338
+ chainId: this.chainId,
339
+ name: eip712.name,
340
+ version: eip712.version,
341
+ gameMaster: this.walletClient.account?.address,
342
+ participantPubKeyHash,
343
+ }, 2);
344
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + timeToJoin);
345
+ //ToDo This is placeholder for now, we will need it later in staking
346
+ const gmCommitment = stringToHex("0x123131231311", { size: 32 });
347
+ console.log({
348
+ name: eip712.name,
349
+ version: eip712.version,
350
+ chainId: this.chainId,
351
+ verifyingContract: instanceAddress,
352
+ }, {
353
+ participant,
354
+ gameId,
355
+ gmCommitment,
356
+ deadline,
357
+ participantPubKeyHash,
358
+ });
359
+ const signature = await this.walletClient.signTypedData({
360
+ domain: {
361
+ name: eip712.name,
362
+ version: eip712.version,
363
+ chainId: this.chainId,
364
+ verifyingContract: instanceAddress,
365
+ },
366
+ types: {
367
+ AttestJoiningGame: [
368
+ { type: "address", name: "participant" },
369
+ { type: "uint256", name: "gameId" },
370
+ { type: "bytes32", name: "gmCommitment" },
371
+ { type: "uint256", name: "deadline" },
372
+ { type: "bytes32", name: "participantPubKeyHash" },
373
+ ],
374
+ },
375
+ message: {
376
+ participant,
377
+ gameId,
378
+ gmCommitment,
379
+ deadline,
380
+ participantPubKeyHash,
381
+ },
382
+ primaryType: "AttestJoiningGame",
383
+ account: this.walletClient.account,
384
+ });
385
+ return { signature, gmCommitment, deadline };
117
386
  };
118
387
  /**
119
388
  * Submits a vote for proposals
@@ -122,7 +391,7 @@ export class GameMaster {
122
391
  * @param voter - Address of the voter
123
392
  * @returns Transaction hash
124
393
  */
125
- submitVote = async ({ instanceAddress, gameId, vote, voter, }) => {
394
+ submitVote = async ({ instanceAddress, gameId, vote, voter, voterSignature, ballotHash, ballotId, }) => {
126
395
  if (!gameId)
127
396
  throw new Error("No gameId");
128
397
  if (!vote)
@@ -130,9 +399,10 @@ export class GameMaster {
130
399
  if (!voter)
131
400
  throw new Error("No voter");
132
401
  const proposerIdx = await this.findPlayerOngoingProposalIndex({ instanceAddress, gameId, player: voter });
133
- if (proposerIdx != -1 && vote[proposerIdx] !== 0n)
402
+ if (proposerIdx == -1)
403
+ throw new Error("You are not a proposer in this game");
404
+ if (vote[proposerIdx] !== 0n)
134
405
  throw new Error("You cannot vote for your own proposal");
135
- const votesHidden = await this.encryptionCallback(JSON.stringify(vote.map((vi) => vi.toString())));
136
406
  if (!this.walletClient?.account?.address)
137
407
  throw new Error("No account address found");
138
408
  try {
@@ -141,7 +411,7 @@ export class GameMaster {
141
411
  address: instanceAddress,
142
412
  abi: RankifyDiamondInstanceAbi,
143
413
  functionName: "submitVote",
144
- args: [gameId, votesHidden, voter],
414
+ args: [gameId, ballotId, voter, zeroHash, voterSignature, ballotHash],
145
415
  });
146
416
  return this.walletClient.writeContract(request);
147
417
  }
@@ -150,14 +420,137 @@ export class GameMaster {
150
420
  }
151
421
  };
152
422
  /**
153
- * Gets the hidden proposer hash for a specific game turn
423
+ * Types for proposal submission
424
+ */
425
+ proposalTypes = {
426
+ SubmitProposal: [
427
+ { type: "uint256", name: "gameId" },
428
+ { type: "address", name: "proposer" },
429
+ { type: "string", name: "encryptedProposal" },
430
+ { type: "uint256", name: "commitment" },
431
+ ],
432
+ };
433
+ signProposal = async ({ verifierAddress, proposer, gameId, encryptedProposal, commitment, eip712, }) => {
434
+ // Generate typed data hash matching Solidity's keccak256(abi.encode(...))
435
+ if (!this.walletClient.account)
436
+ throw new Error("No account");
437
+ return this.walletClient.signTypedData({
438
+ domain: {
439
+ name: eip712.name,
440
+ version: eip712.version,
441
+ chainId: this.chainId,
442
+ verifyingContract: verifierAddress,
443
+ },
444
+ types: this.proposalTypes,
445
+ message: {
446
+ gameId,
447
+ proposer,
448
+ encryptedProposal,
449
+ commitment,
450
+ },
451
+ primaryType: "SubmitProposal",
452
+ account: this.walletClient.account,
453
+ });
454
+ };
455
+ proposalValues = async ({ instanceAddress, gameId, proposal, proposer, turn, }) => {
456
+ const instance = new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
457
+ const proposerPubKey = await instance.getPlayerPubKey({
458
+ instanceAddress,
459
+ gameId,
460
+ player: proposer,
461
+ });
462
+ const sharedKey = instance.sharedSigner({
463
+ publicKey: proposerPubKey,
464
+ privateKey: await this.gameKey({ gameId, contractAddress: instanceAddress }),
465
+ gameId,
466
+ turn,
467
+ contractAddress: instanceAddress,
468
+ chainId: this.chainId,
469
+ });
470
+ // const poseidon = await buildPoseidon();
471
+ const proposalValue = BigInt(keccak256(encodePacked(["string"], [proposal])));
472
+ const randomnessValue = BigInt(keccak256(encodePacked(["string"], [sharedKey])));
473
+ // Calculate commitment using poseidon
474
+ return {
475
+ proposalValue,
476
+ randomnessValue,
477
+ proposal,
478
+ };
479
+ };
480
+ /**
481
+ * Encrypts a proposal
482
+ * @param proposal - Proposal to encrypt
483
+ * @param turn - Turn number
484
+ * @param instanceAddress - Address of the game instance
485
+ * @param gameId - ID of the game
486
+ * @param proposerPubKey - Public key of the proposer
487
+ * @returns Encrypted proposal and shared key
488
+ */
489
+ encryptProposal = async ({ proposal, turn, instanceAddress, gameId, proposerPubKey, }) => {
490
+ const instance = new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
491
+ const sharedKey = instance.sharedSigner({
492
+ publicKey: proposerPubKey,
493
+ privateKey: await this.gameKey({ gameId, contractAddress: instanceAddress }),
494
+ gameId,
495
+ turn,
496
+ contractAddress: instanceAddress,
497
+ chainId: this.chainId,
498
+ });
499
+ logger(`Encrypting proposal ${proposal} with shared key (hashed value: ${keccak256(sharedKey)})`);
500
+ const encryptedProposal = aes.encrypt(proposal, sharedKey).toString();
501
+ logger(`Encrypted proposal ${encryptedProposal}`);
502
+ return { encryptedProposal, sharedKey };
503
+ };
504
+ /**
505
+ * Attests a proposal
506
+ * @param instanceAddress - Address of the game instance
154
507
  * @param gameId - ID of the game
508
+ * @param proposal - Proposal to attest
509
+ * @param proposerPubKey - Public key of the proposer
155
510
  * @param turn - Turn number
156
- * @param proposer - Address of the proposer
157
- * @returns Hidden proposer hash
511
+ * @returns The attested proposal
158
512
  */
159
- proposerHidden = ({ gameId, turn, proposer }) => {
160
- return this.getTurnPlayersSalt({ gameId, turn, proposer }).then((salt) => keccak256(encodePacked(["address", "bytes32"], [proposer, salt])));
513
+ attestProposal = async ({ instanceAddress, gameId, proposal, proposerPubKey, turn, }) => {
514
+ const proposerAddress = publicKeyToAddress(proposerPubKey);
515
+ logger(`Creating proposal secrets for player ${proposerAddress} in game ${gameId}`);
516
+ const poseidon = await buildPoseidon();
517
+ const instance = new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
518
+ const { encryptedProposal, sharedKey } = await this.encryptProposal({
519
+ proposal,
520
+ turn,
521
+ instanceAddress,
522
+ gameId,
523
+ proposerPubKey,
524
+ });
525
+ const proposalValue = BigInt(keccak256(encodePacked(["string"], [proposal])));
526
+ const randomnessValue = BigInt(keccak256(encodePacked(["string"], [sharedKey])));
527
+ // Calculate commitment using poseidon
528
+ const hash = poseidon([proposalValue, randomnessValue]);
529
+ const poseidonCommitment = BigInt(poseidon.F.toObject(hash));
530
+ const eip712 = await instance.getEIP712Domain();
531
+ const signature = await this.signProposal({
532
+ verifierAddress: instanceAddress,
533
+ proposer: proposerAddress,
534
+ gameId,
535
+ encryptedProposal,
536
+ commitment: poseidonCommitment,
537
+ eip712,
538
+ });
539
+ const params = {
540
+ gameId,
541
+ encryptedProposal,
542
+ commitment: poseidonCommitment,
543
+ proposer: proposerAddress,
544
+ gmSignature: signature,
545
+ };
546
+ logger(`Generated proposal secrets with commitment ${poseidonCommitment}`);
547
+ return {
548
+ submissionParams: params,
549
+ proposal,
550
+ proposerAddress,
551
+ proposalValue,
552
+ randomnessValue,
553
+ };
161
554
  };
162
555
  /**
163
556
  * Submits a proposal to the game
@@ -167,18 +560,22 @@ export class GameMaster {
167
560
  * @param proposer - Address of the proposer
168
561
  * @returns Transaction hash
169
562
  */
170
- submitProposal = async ({ instanceAddress, gameId, commitmentHash, proposal, proposer, }) => {
563
+ submitProposal = async ({ instanceAddress, submissionParams, proposerSignature, }) => {
171
564
  // let proposalData: GetAbiItemParameters<typeof RankifyDiamondInstanceAbi, "submitProposal">["args"];
172
565
  // proposalData[0].
173
- const encryptedProposal = await this.encryptionCallback(proposal);
174
- console.log("submitting proposal tx..", gameId, commitmentHash, proposal, proposer);
566
+ const txParams = [
567
+ {
568
+ ...submissionParams,
569
+ proposerSignature,
570
+ },
571
+ ];
175
572
  try {
176
573
  const { request } = await this.publicClient.simulateContract({
177
574
  account: this.walletClient.account,
178
575
  address: instanceAddress,
179
576
  abi: RankifyDiamondInstanceAbi,
180
577
  functionName: "submitProposal",
181
- args: [{ gameId, commitmentHash, encryptedProposal, proposer }],
578
+ args: txParams,
182
579
  });
183
580
  return this.walletClient.writeContract(request);
184
581
  }
@@ -199,18 +596,28 @@ export class GameMaster {
199
596
  eventName: "VoteSubmitted",
200
597
  args: { gameId, turn },
201
598
  });
202
- const votes = await Promise.all(evts.map(async (event) => {
599
+ logger(`Found ${evts.length} events`);
600
+ if (evts.length === 0)
601
+ return [];
602
+ // Process events one by one to allow errors to propagate
603
+ const votes = [];
604
+ for (const event of evts) {
203
605
  if (!event.args.player)
204
- throw new Error("No player found in event data, that is unexpected");
205
- if (!event.args.votesHidden)
206
- throw new Error("No votesHidden found in event data, that is unexpected");
207
- const decryptedVote = await this.decryptionCallback(event.args.votesHidden);
208
- const parsedVotes = JSON.parse(decryptedVote);
209
- return {
606
+ throw new Error("No player in event");
607
+ if (!event.args.sealedBallotId)
608
+ throw new Error("No sealedBallotId in event");
609
+ const turnKey = await this.calculateSharedTurnKey({
610
+ instanceAddress,
611
+ gameId,
612
+ turn,
210
613
  player: event.args.player,
211
- votes: parsedVotes.map((v) => BigInt(v)),
212
- };
213
- }));
614
+ });
615
+ const decryptedVotes = await this.decryptVote(event.args.sealedBallotId, turnKey);
616
+ votes.push({
617
+ player: event.args.player,
618
+ votes: decryptedVotes,
619
+ });
620
+ }
214
621
  return votes;
215
622
  };
216
623
  /**
@@ -303,81 +710,50 @@ export class GameMaster {
303
710
  if (!Array.isArray(players)) {
304
711
  throw new Error("Expected players to be an array");
305
712
  }
306
- const oldProposals = [];
307
713
  const proposerIndices = [];
308
- let votes = [];
309
- //Proposals sequence is directly corresponding to proposers sequence
310
- if (turn != 1n) {
311
- const endedEvents = await this.publicClient.getContractEvents({
312
- address: instanceAddress,
313
- abi: RankifyDiamondInstanceAbi,
314
- eventName: "TurnEnded",
315
- args: { gameId, turn: turn - 1n },
316
- });
317
- const evt = endedEvents[0];
318
- if (endedEvents.length > 1)
319
- throw new Error("Multiple turns ended");
320
- const args = evt.args;
321
- const decryptedProposals = await this.decryptProposals({ instanceAddress, gameId, turn: turn - 1n });
322
- if (args.newProposals) {
323
- args.newProposals.forEach((proposal, idx) => {
324
- const proposer = decryptedProposals.find((p) => p.proposal === proposal)?.proposer;
325
- if (!proposer)
326
- throw new Error("No proposer found for proposal");
327
- oldProposals[idx] = {
328
- proposer,
329
- proposal: proposal,
330
- };
331
- });
332
- }
333
- else {
334
- // Boundary case if no-one proposed a thing
335
- players.forEach((p, idx) => {
336
- oldProposals[idx] = {
337
- proposer: p,
338
- proposal: "",
339
- };
340
- });
341
- }
342
- votes = await this.decryptTurnVotes({ instanceAddress, gameId, turn }).then((voteSubmissions) => {
343
- const orderedVotes = players.map((player) => ({
344
- player,
345
- votes: new Array(players.length).fill(0n),
346
- }));
347
- players.forEach((player, playerIdx) => {
348
- const vote = voteSubmissions.find((v) => v.player === player);
349
- if (vote)
350
- orderedVotes[playerIdx] = vote;
351
- else
352
- orderedVotes[playerIdx] = {
353
- player,
354
- votes: new Array(players.length).fill(0n),
355
- };
356
- });
357
- return orderedVotes;
358
- });
359
- }
360
- const newProposals = await this.decryptProposals({ instanceAddress, gameId, turn });
714
+ const oldProposals = await this.getProposalsVotedUpon({ instanceAddress, gameId, turn });
715
+ const decryptedProposals = await this.decryptProposals({ instanceAddress, gameId, turn });
716
+ const proposals = players.map((player) => {
717
+ const proposal = decryptedProposals.find((p) => p.proposer === player)?.proposal ?? "";
718
+ return {
719
+ proposer: player,
720
+ proposal,
721
+ };
722
+ });
361
723
  players.forEach((player) => {
362
724
  let proposerIdx = oldProposals.findIndex((p) => player === p.proposer);
363
725
  if (proposerIdx === -1)
364
726
  proposerIdx = players.length; //Did not propose
365
727
  proposerIndices.push(BigInt(proposerIdx));
366
728
  });
729
+ const voteDecrypted = await this.decryptTurnVotes({ instanceAddress, gameId, turn });
730
+ const votes = await Promise.all(players.map(async (player) => {
731
+ const vote = voteDecrypted.find((v) => v.player === player);
732
+ if (!vote?.votes)
733
+ return players.map(() => 0n);
734
+ return vote.votes;
735
+ }));
367
736
  const tableData = players.map((player, idx) => ({
368
737
  player,
369
738
  proposerIndex: proposerIndices[idx],
370
739
  proposer: oldProposals[Number(proposerIndices[idx])].proposer,
371
740
  }));
372
741
  console.table(tableData);
373
- const shuffled = await this.shuffle(newProposals.map((x) => x.proposal));
374
- console.log(votes.map((v) => v.votes));
742
+ const attested = await this.getProposalsIntegrity({
743
+ gameId,
744
+ turn,
745
+ verifierAddress: instanceAddress,
746
+ size: players.length,
747
+ proposals,
748
+ });
749
+ logger(`votes:`);
750
+ logger(votes);
375
751
  const { request } = await this.publicClient.simulateContract({
376
752
  abi: RankifyDiamondInstanceAbi,
377
753
  account: this.walletClient.account,
378
754
  address: instanceAddress,
379
755
  functionName: "endTurn",
380
- args: [gameId, votes.map((v) => v.votes), shuffled, proposerIndices],
756
+ args: [gameId, votes, attested.newProposals, attested.permutation, attested.nullifier],
381
757
  });
382
758
  return this.walletClient.writeContract(request);
383
759
  }
@@ -385,5 +761,301 @@ export class GameMaster {
385
761
  throw await handleRPCError(e);
386
762
  }
387
763
  };
764
+ gameKey = async ({ gameId, contractAddress }) => {
765
+ logger(`Signing game key for game ${gameId} at address ${contractAddress}`);
766
+ const message = encodePacked(["uint256", "address", "string"], [gameId, contractAddress, "gameKey"]);
767
+ logger(`Signing message: ${message}`, 2);
768
+ if (!this.walletClient.account)
769
+ throw new Error("No account");
770
+ const gameKey = await this.walletClient
771
+ .signMessage({
772
+ message,
773
+ account: this.walletClient.account,
774
+ })
775
+ .then((sig) => keccak256(sig));
776
+ logger(`Game key: ${gameKey}`, 2);
777
+ return gameKey;
778
+ };
779
+ calculateSharedTurnKey = async ({ instanceAddress, gameId, turn, player, }) => {
780
+ logger(`Calculating shared turn key for player ${player} in game ${gameId} at address ${instanceAddress}`);
781
+ const instance = new InstanceBase({ instanceAddress, publicClient: this.publicClient, chainId: this.chainId });
782
+ const playerPubKey = await instance.getPlayerPubKey({ instanceAddress, gameId, player });
783
+ logger(`Player public key: ${playerPubKey}`, 2);
784
+ return instance.sharedSigner({
785
+ publicKey: playerPubKey,
786
+ privateKey: await this.gameKey({ gameId, contractAddress: instanceAddress }),
787
+ gameId,
788
+ turn,
789
+ contractAddress: instanceAddress,
790
+ chainId: this.chainId,
791
+ });
792
+ };
793
+ decryptVote = async (vote, privateKey) => {
794
+ const decrypted = aes.decrypt(vote, privateKey).toString(cryptoJs.enc.Utf8);
795
+ if (!decrypted) {
796
+ throw new Error("Failed to decrypt vote");
797
+ }
798
+ try {
799
+ const parsed = JSON.parse(decrypted);
800
+ logger(`Decrypted vote:`, 2);
801
+ logger(parsed, 2);
802
+ return parsed.map((v) => BigInt(v));
803
+ // eslint-disable-next-line
804
+ }
805
+ catch (e) {
806
+ throw new Error("Unexpected token");
807
+ }
808
+ };
809
+ /**
810
+ * Creates and signs a vote for testing purposes
811
+ * @param params - Parameters including voter, game info, and vote configuration
812
+ * @returns A complete mock vote with signatures
813
+ */
814
+ attestVote = async ({ voter, gameId, turn, vote, verifierAddress, }) => {
815
+ logger(`Attesting vote for player ${voter} in game ${gameId}, turn ${turn}`);
816
+ const gameSize = (await this.getPlayers({ instanceAddress: verifierAddress, gameId })).length;
817
+ const instance = new InstanceBase({
818
+ instanceAddress: verifierAddress,
819
+ publicClient: this.publicClient,
820
+ chainId: this.chainId,
821
+ });
822
+ const eip712 = await instance.getEIP712Domain();
823
+ const playerSalt = await this.getTurnPlayersSalt({
824
+ gameId,
825
+ turn,
826
+ player: voter,
827
+ verifierAddress,
828
+ size: gameSize,
829
+ });
830
+ const ballot = {
831
+ vote: vote,
832
+ salt: playerSalt,
833
+ };
834
+ const ballotHash = keccak256(encodePacked(["uint256[]", "bytes32"], [vote, playerSalt]));
835
+ const turnKey = await this.calculateSharedTurnKey({
836
+ instanceAddress: verifierAddress,
837
+ gameId,
838
+ turn,
839
+ player: voter,
840
+ });
841
+ const ballotId = aes.encrypt(JSON.stringify(ballot.vote.map((v) => v.toString())), turnKey).toString();
842
+ const gmSignature = await this.signVote({
843
+ verifierAddress,
844
+ voter,
845
+ gameId,
846
+ sealedBallotId: ballotId,
847
+ ballotHash,
848
+ name: eip712.name,
849
+ version: eip712.version,
850
+ });
851
+ logger(`Vote attested for player ${voter} by ${this.walletClient.account?.address}`);
852
+ logger({
853
+ gameId,
854
+ turn,
855
+ vote,
856
+ verifierAddress,
857
+ gameSize,
858
+ name: eip712.name,
859
+ version: eip712.version,
860
+ chainId: this.chainId,
861
+ }, 2);
862
+ return { vote, ballotHash, ballot, ballotId, gmSignature };
863
+ };
864
+ /**
865
+ * Signs a vote
866
+ * @param params - Parameters including voter, game info, and vote configuration
867
+ * @returns The signed vote
868
+ */
869
+ signVote = async (params) => {
870
+ const { voter, gameId, verifierAddress, sealedBallotId, ballotHash, name, version } = params;
871
+ logger(`Signing vote for player ${voter} in game ${gameId}`);
872
+ const types = {
873
+ SubmitVote: [
874
+ { name: "gameId", type: "uint256" },
875
+ { name: "voter", type: "address" },
876
+ { name: "sealedBallotId", type: "string" },
877
+ { name: "ballotHash", type: "bytes32" },
878
+ ],
879
+ };
880
+ if (!this.walletClient.account)
881
+ throw new Error("No account");
882
+ const signature = await this.walletClient.signTypedData({
883
+ domain: {
884
+ name,
885
+ version,
886
+ chainId: this.chainId,
887
+ verifyingContract: verifierAddress,
888
+ },
889
+ types,
890
+ primaryType: "SubmitVote",
891
+ message: {
892
+ gameId,
893
+ voter,
894
+ sealedBallotId,
895
+ ballotHash,
896
+ },
897
+ account: this.walletClient.account,
898
+ });
899
+ logger(`Vote signed for player ${voter}`);
900
+ return signature;
901
+ };
902
+ /**
903
+ * Generates integrity data for the end of a game turn
904
+ * @param params - Parameters including game info, turn, and proposal data
905
+ * @returns Integrity data including permutation, secret, and proof
906
+ */
907
+ generateEndTurnIntegrity = async ({ gameId, turn, verifierAddress, size = 15, proposals, }) => {
908
+ const maxSize = 15;
909
+ const { permutation, secret: nullifier } = await this.generateDeterministicPermutation({
910
+ gameId,
911
+ turn: turn - 1n,
912
+ verifierAddress,
913
+ size,
914
+ });
915
+ const values = await Promise.all(proposals.map((p) => p.proposal === ""
916
+ ? {
917
+ proposalValue: 0n,
918
+ randomnessValue: 0n,
919
+ proposer: p.proposer,
920
+ }
921
+ : this.proposalValues({
922
+ instanceAddress: verifierAddress,
923
+ gameId,
924
+ proposal: p.proposal,
925
+ turn,
926
+ proposer: p.proposer,
927
+ })));
928
+ const inputs = await this.createInputs({
929
+ numActive: size,
930
+ proposals: values.map((v) => v.proposalValue),
931
+ commitmentRandomnesses: values.map((v) => v.randomnessValue),
932
+ gameId,
933
+ turn,
934
+ verifierAddress,
935
+ });
936
+ logger(inputs, 2);
937
+ // Apply permutation to proposals array
938
+ const permutedProposals = [...proposals];
939
+ for (let i = 0; i < maxSize; i++) {
940
+ if (i < size) {
941
+ permutedProposals[Number(inputs.permutation[i])] = proposals[i];
942
+ }
943
+ }
944
+ const config = {
945
+ circuitName: "ProposalsIntegrity15",
946
+ // node_modules/rankify-contracts/zk_artifacts
947
+ circuitArtifactsPath: path.join(__dirname, "../../node_modules/rankify-contracts/zk_artifacts/circuits/proposals_integrity_15.circom/"),
948
+ verifierDirPath: path.join(__dirname, "../../node_modules/rankify-contracts/src/verifiers"),
949
+ };
950
+ const implementer = new Groth16Implementer();
951
+ const circuit = new CircuitZKit(config, implementer);
952
+ const proof = await circuit.generateProof(inputs);
953
+ const callData = await circuit.generateCalldata(proof);
954
+ // const circuit = await hre.zkit.getCircuit("ProposalsIntegrity15");
955
+ // const inputsKey = ethers.utils.solidityKeccak256(["string"], [JSON.stringify(inputs) + "groth16"]);
956
+ // let cached = loadFromCache(inputsKey);
957
+ // if (cached) {
958
+ // log(`Loaded proof from cache for inputsKey ${inputsKey}`, 2);
959
+ // } else {
960
+ // log(`Generating proof for inputsKey ${inputsKey}`, 2);
961
+ // const proof = await circuit.generateProof(inputs);
962
+ // saveToCache(inputsKey, proof);
963
+ // cached = proof;
964
+ // }
965
+ // const proof = "0x00";
966
+ if (!proof) {
967
+ throw new Error("Proof not found");
968
+ }
969
+ // const callData = await circuit.generateCalldata(proof);
970
+ const a = callData[0].map((a) => BigInt(a));
971
+ const b = callData[1].map((b) => b.map((b) => BigInt(b)));
972
+ const c = callData[2].map((c) => BigInt(c));
973
+ return {
974
+ commitment: inputs.permutationCommitment,
975
+ nullifier,
976
+ permutation: permutation.slice(0, size),
977
+ permutedProposals: permutedProposals.map((proposal) => proposal.proposal),
978
+ a,
979
+ b,
980
+ c,
981
+ };
982
+ };
983
+ /**
984
+ * Gets proposal integrity data for testing
985
+ * @param params - Parameters including game info and proposal data
986
+ * @returns Proposal integrity information including permutations and proofs
987
+ */
988
+ async getProposalsIntegrity({ size, gameId, turn, proposals, verifierAddress, }) {
989
+ logger(`Generating proposals integrity for game ${gameId}, turn ${turn} with ${size} players.`);
990
+ const { commitment, nullifier, permutation, permutedProposals, a, b, c } = await this.generateEndTurnIntegrity({
991
+ gameId,
992
+ turn,
993
+ verifierAddress,
994
+ size,
995
+ proposals,
996
+ });
997
+ logger(`Generated proposals integrity with commitment ${commitment}`);
998
+ return {
999
+ newProposals: {
1000
+ a,
1001
+ b,
1002
+ c,
1003
+ proposals: permutedProposals,
1004
+ permutationCommitment: commitment,
1005
+ },
1006
+ permutation: permutation.map((p) => BigInt(p)),
1007
+ proposalsNotPermuted: proposals.map((proposal) => proposal.proposal),
1008
+ nullifier,
1009
+ };
1010
+ }
1011
+ /**
1012
+ * Creates inputs for the proposal integrity circuit
1013
+ * @param params - Parameters including number of active proposals, proposals, commitment random numbers, game ID, turn, and verifier address
1014
+ * @returns The inputs for the proposal integrity circuit
1015
+ */
1016
+ createInputs = async ({ numActive, proposals, commitmentRandomnesses, gameId, turn, verifierAddress, }) => {
1017
+ const poseidon = await buildPoseidon();
1018
+ const maxSize = 15;
1019
+ // Initialize arrays with zeros
1020
+ const commitments = Array(maxSize).fill(0n);
1021
+ const randomnesses = Array(maxSize).fill(0n);
1022
+ const permutedProposals = Array(maxSize).fill(0n);
1023
+ // Generate deterministic permutation
1024
+ const { permutation, secret, commitment } = await this.generateDeterministicPermutation({
1025
+ gameId,
1026
+ turn,
1027
+ verifierAddress,
1028
+ size: numActive,
1029
+ });
1030
+ // Fill arrays with values
1031
+ for (let i = 0; i < maxSize; i++) {
1032
+ if (i < numActive) {
1033
+ // Active slots
1034
+ const proposal = proposals[i];
1035
+ const randomness = commitmentRandomnesses[i];
1036
+ const hash = poseidon([proposal, randomness]);
1037
+ commitments[i] = BigInt(poseidon.F.toObject(hash));
1038
+ randomnesses[i] = randomness;
1039
+ // Store proposal in permuted position
1040
+ permutedProposals[permutation[i]] = proposal;
1041
+ }
1042
+ else {
1043
+ // Inactive slots
1044
+ const hash = poseidon([0n, 0n]);
1045
+ commitments[i] = BigInt(poseidon.F.toObject(hash));
1046
+ randomnesses[i] = 0n;
1047
+ // permutedProposals already 0n
1048
+ }
1049
+ }
1050
+ return {
1051
+ numActive: BigInt(numActive),
1052
+ commitments,
1053
+ permutedProposals,
1054
+ permutationCommitment: commitment,
1055
+ permutation: permutation.map((p) => BigInt(p)),
1056
+ randomnesses,
1057
+ permutationRandomness: secret,
1058
+ };
1059
+ };
388
1060
  }
389
1061
  //# sourceMappingURL=GameMaster.js.map