From 02843a5e0ca81294bc1c4533741b6b6d5823320b Mon Sep 17 00:00:00 2001 From: Mugen Date: Thu, 26 Feb 2026 09:14:07 +0100 Subject: [PATCH] feat: scaffold typed guilds sdk core client modules --- sdk/package-lock.json | 1459 +++++++++++++++++++++++++++++++ sdk/package.json | 79 ++ sdk/src/bindings/factory.ts | 71 ++ sdk/src/bindings/guild.ts | 111 +++ sdk/src/bindings/index.ts | 2 + sdk/src/client/create-client.ts | 7 + sdk/src/client/guilds-client.ts | 161 ++++ sdk/src/client/index.ts | 2 + sdk/src/config/index.ts | 1 + sdk/src/config/networks.ts | 7 + sdk/src/core/index.ts | 1 + sdk/src/core/transport.ts | 14 + sdk/src/errors/index.ts | 28 + sdk/src/index.ts | 7 + sdk/src/types/contracts.ts | 60 ++ sdk/src/types/index.ts | 2 + sdk/src/types/network.ts | 21 + sdk/src/utils/address.ts | 13 + sdk/src/utils/index.ts | 2 + sdk/src/utils/retry.ts | 49 ++ sdk/tsconfig.build.json | 9 + sdk/tsconfig.examples.json | 9 + sdk/tsconfig.json | 21 + 23 files changed, 2136 insertions(+) create mode 100644 sdk/package-lock.json create mode 100644 sdk/package.json create mode 100644 sdk/src/bindings/factory.ts create mode 100644 sdk/src/bindings/guild.ts create mode 100644 sdk/src/bindings/index.ts create mode 100644 sdk/src/client/create-client.ts create mode 100644 sdk/src/client/guilds-client.ts create mode 100644 sdk/src/client/index.ts create mode 100644 sdk/src/config/index.ts create mode 100644 sdk/src/config/networks.ts create mode 100644 sdk/src/core/index.ts create mode 100644 sdk/src/core/transport.ts create mode 100644 sdk/src/errors/index.ts create mode 100644 sdk/src/index.ts create mode 100644 sdk/src/types/contracts.ts create mode 100644 sdk/src/types/index.ts create mode 100644 sdk/src/types/network.ts create mode 100644 sdk/src/utils/address.ts create mode 100644 sdk/src/utils/index.ts create mode 100644 sdk/src/utils/retry.ts create mode 100644 sdk/tsconfig.build.json create mode 100644 sdk/tsconfig.examples.json create mode 100644 sdk/tsconfig.json diff --git a/sdk/package-lock.json b/sdk/package-lock.json new file mode 100644 index 0000000..356f17a --- /dev/null +++ b/sdk/package-lock.json @@ -0,0 +1,1459 @@ +{ + "name": "@runelabsxyz/guilds-sdk", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@runelabsxyz/guilds-sdk", + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "@types/node": "^22.10.2", + "typescript": "^5.7.3", + "vitest": "^2.1.8" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.12.tgz", + "integrity": "sha512-0QEp0aPJYSyf6RrTjDB7HlKgNMTY+V2C7ESTaVt6G9gQ0rPLzTGz7OF2NXTLR5vcy7HJEtIUsyWLsfX0kTqJBA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@vitest/expect": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", + "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.9", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.9", + "@vitest/mocker": "2.1.9", + "@vitest/pretty-format": "^2.1.9", + "@vitest/runner": "2.1.9", + "@vitest/snapshot": "2.1.9", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.9", + "@vitest/ui": "2.1.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/sdk/package.json b/sdk/package.json new file mode 100644 index 0000000..0d4ee7a --- /dev/null +++ b/sdk/package.json @@ -0,0 +1,79 @@ +{ + "name": "@runelabsxyz/guilds-sdk", + "version": "0.1.0", + "description": "Typed TypeScript SDK for RuneLabs Guilds contracts", + "license": "MIT", + "type": "module", + "sideEffects": false, + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist", + "README.md", + "CHANGELOG.md", + "scripts", + "generated" + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./core": { + "types": "./dist/core/index.d.ts", + "import": "./dist/core/index.js" + }, + "./types": { + "types": "./dist/types/index.d.ts", + "import": "./dist/types/index.js" + }, + "./utils": { + "types": "./dist/utils/index.d.ts", + "import": "./dist/utils/index.js" + }, + "./errors": { + "types": "./dist/errors/index.d.ts", + "import": "./dist/errors/index.js" + }, + "./client": { + "types": "./dist/client/index.d.ts", + "import": "./dist/client/index.js" + }, + "./bindings": { + "types": "./dist/bindings/index.d.ts", + "import": "./dist/bindings/index.js" + }, + "./config": { + "types": "./dist/config/index.d.ts", + "import": "./dist/config/index.js" + }, + "./package.json": "./package.json" + }, + "scripts": { + "clean": "rm -rf dist", + "build": "tsc -p tsconfig.build.json", + "typecheck": "tsc -p tsconfig.json --noEmit", + "typecheck:examples": "tsc -p tsconfig.examples.json --noEmit", + "test": "vitest run", + "test:watch": "vitest", + "sync:contracts": "node ./scripts/sync-contract-signature.mjs", + "check:compat": "node ./scripts/check-contract-compat.mjs", + "verify": "npm run typecheck && npm run typecheck:examples && npm run check:compat && npm run test && npm run build" + }, + "keywords": [ + "starknet", + "guilds", + "runelabs", + "sdk", + "typescript" + ], + "engines": { + "node": ">=20" + }, + "devDependencies": { + "@types/node": "^22.10.2", + "typescript": "^5.7.3", + "vitest": "^2.1.8" + } +} diff --git a/sdk/src/bindings/factory.ts b/sdk/src/bindings/factory.ts new file mode 100644 index 0000000..e5aea05 --- /dev/null +++ b/sdk/src/bindings/factory.ts @@ -0,0 +1,71 @@ +import type { ContractTransport } from '../core/transport.js'; +import type { CreateGuildParams, GuildAddresses, StarknetAddress } from '../types/contracts.js'; + +export interface FactoryBindings { + createGuild(factory: StarknetAddress, params: CreateGuildParams): Promise<{ transactionHash: string }>; + getGuild(factory: StarknetAddress, guildAddress: StarknetAddress): Promise; + isNameTaken(factory: StarknetAddress, name: string): Promise; + isTickerTaken(factory: StarknetAddress, ticker: string): Promise; +} + +function toBool(word: string): boolean { + return word !== '0x0' && word !== '0'; +} + +export function createFactoryBindings(transport: ContractTransport): FactoryBindings { + return { + async createGuild(factory, params): Promise<{ transactionHash: string }> { + const calldata = [ + params.name, + params.ticker, + params.depositToken, + `0x${params.depositAmount.toString(16)}`, + `0x${params.initialTokenSupply.toString(16)}`, + `0x${params.governorConfig.votingDelay.toString(16)}`, + `0x${params.governorConfig.votingPeriod.toString(16)}`, + `0x${params.governorConfig.proposalThreshold.toString(16)}`, + `0x${params.governorConfig.quorumBps.toString(16)}`, + `0x${params.governorConfig.timelockDelay.toString(16)}`, + ]; + return transport.invoke({ + contractAddress: factory, + entrypoint: 'create_guild', + calldata, + }); + }, + + async getGuild(factory, guildAddress): Promise { + return transport.call({ + contractAddress: factory, + entrypoint: 'get_guild', + calldata: [guildAddress], + }); + }, + + async isNameTaken(factory, name): Promise { + const raw = await transport.call({ + contractAddress: factory, + entrypoint: 'is_name_taken', + calldata: [name], + }); + return toBool(raw[0] ?? '0x0'); + }, + + async isTickerTaken(factory, ticker): Promise { + const raw = await transport.call({ + contractAddress: factory, + entrypoint: 'is_ticker_taken', + calldata: [ticker], + }); + return toBool(raw[0] ?? '0x0'); + }, + }; +} + +export function decodeGuildAddresses(raw: string[]): GuildAddresses { + return { + guild: raw[0] as StarknetAddress, + token: raw[1] as StarknetAddress, + governor: raw[2] as StarknetAddress, + }; +} diff --git a/sdk/src/bindings/guild.ts b/sdk/src/bindings/guild.ts new file mode 100644 index 0000000..4076129 --- /dev/null +++ b/sdk/src/bindings/guild.ts @@ -0,0 +1,111 @@ +import type { ContractTransport } from '../core/transport.js'; +import type { + GovernanceActionParams, + ShareActionParams, + StarknetAddress, + TreasuryActionParams, + VoteParams, + WireGuildAddressesParams, +} from '../types/contracts.js'; + +export interface GuildBindings { + setGovernorAddress(guild: StarknetAddress, governor: StarknetAddress): Promise<{ transactionHash: string }>; + executeCoreAction(params: TreasuryActionParams): Promise<{ transactionHash: string }>; + buyShares(params: ShareActionParams): Promise<{ transactionHash: string }>; + redeemShares(params: ShareActionParams): Promise<{ transactionHash: string }>; + getGovernorAddress(guild: StarknetAddress): Promise; + getTokenAddress(guild: StarknetAddress): Promise; + propose(params: GovernanceActionParams): Promise<{ transactionHash: string }>; + vote(params: VoteParams): Promise<{ transactionHash: string }>; +} + +export function createGuildBindings(transport: ContractTransport): GuildBindings { + return { + async setGovernorAddress(guild, governor): Promise<{ transactionHash: string }> { + return transport.invoke({ + contractAddress: guild, + entrypoint: 'set_governor_address', + calldata: [governor], + }); + }, + + async executeCoreAction(params): Promise<{ transactionHash: string }> { + const calldata = [ + `0x${params.actionType.toString(16)}`, + params.target, + params.token, + `0x${params.amount.toString(16)}`, + `0x${params.calldata.length.toString(16)}`, + ...params.calldata, + ]; + return transport.invoke({ + contractAddress: params.guild, + entrypoint: 'execute_core_action', + calldata, + }); + }, + + async buyShares(params): Promise<{ transactionHash: string }> { + return transport.invoke({ + contractAddress: params.guild, + entrypoint: 'buy_shares', + calldata: [`0x${params.amount.toString(16)}`], + }); + }, + + async redeemShares(params): Promise<{ transactionHash: string }> { + return transport.invoke({ + contractAddress: params.guild, + entrypoint: 'redeem_shares', + calldata: [`0x${params.amount.toString(16)}`], + }); + }, + + async getGovernorAddress(guild): Promise { + const raw = await transport.call({ + contractAddress: guild, + entrypoint: 'get_governor_address', + calldata: [], + }); + return raw[0] as StarknetAddress; + }, + + async getTokenAddress(guild): Promise { + const raw = await transport.call({ + contractAddress: guild, + entrypoint: 'get_token_address', + calldata: [], + }); + return raw[0] as StarknetAddress; + }, + + async propose(params): Promise<{ transactionHash: string }> { + const calldata = [ + `0x${params.targets.length.toString(16)}`, + ...params.targets, + `0x${params.values.length.toString(16)}`, + ...params.values.map((v) => `0x${v.toString(16)}`), + `0x${params.calldatas.length.toString(16)}`, + ...params.calldatas, + params.description, + ]; + return transport.invoke({ + contractAddress: params.governor, + entrypoint: 'propose', + calldata, + }); + }, + + async vote(params): Promise<{ transactionHash: string }> { + return transport.invoke({ + contractAddress: params.governor, + entrypoint: 'cast_vote', + calldata: [`0x${params.proposalId.toString(16)}`, `0x${params.support.toString(16)}`], + }); + }, + }; +} + +export function wireAddresses(input: WireGuildAddressesParams): WireGuildAddressesParams { + return input; +} diff --git a/sdk/src/bindings/index.ts b/sdk/src/bindings/index.ts new file mode 100644 index 0000000..fc15038 --- /dev/null +++ b/sdk/src/bindings/index.ts @@ -0,0 +1,2 @@ +export * from './factory.js'; +export * from './guild.js'; diff --git a/sdk/src/client/create-client.ts b/sdk/src/client/create-client.ts new file mode 100644 index 0000000..df7a367 --- /dev/null +++ b/sdk/src/client/create-client.ts @@ -0,0 +1,7 @@ +import type { ContractTransport } from '../core/transport.js'; +import type { GuildsClientOptions } from '../types/network.js'; +import { DefaultGuildsClient, type GuildsClient } from './guilds-client.js'; + +export function createGuildsClient(transport: ContractTransport, options: GuildsClientOptions): GuildsClient { + return new DefaultGuildsClient(transport, options); +} diff --git a/sdk/src/client/guilds-client.ts b/sdk/src/client/guilds-client.ts new file mode 100644 index 0000000..40672f3 --- /dev/null +++ b/sdk/src/client/guilds-client.ts @@ -0,0 +1,161 @@ +import { createFactoryBindings, decodeGuildAddresses } from '../bindings/factory.js'; +import { createGuildBindings, wireAddresses } from '../bindings/guild.js'; +import type { FactoryBindings } from '../bindings/factory.js'; +import type { GuildBindings } from '../bindings/guild.js'; +import type { ContractTransport } from '../core/transport.js'; +import { DEFAULT_NETWORK_ADDRESSES } from '../config/networks.js'; +import { GuildsSdkError, toGuildsSdkError } from '../errors/index.js'; +import type { + CreateGuildParams, + GovernanceActionParams, + GuildAddresses, + ShareActionParams, + StarknetAddress, + TreasuryActionParams, + VoteParams, + WireGuildAddressesParams, +} from '../types/contracts.js'; +import type { GuildsClientOptions } from '../types/network.js'; +import type { GuildsNetwork } from '../types/network.js'; +import { assertAddress } from '../utils/address.js'; +import { withRetry } from '../utils/retry.js'; + +export interface GuildsClient { + readonly network: GuildsNetwork; + readonly addresses: { + factory: StarknetAddress | undefined; + guildTemplate: StarknetAddress | undefined; + tokenTemplate: StarknetAddress | undefined; + governorTemplate: StarknetAddress | undefined; + }; + createGuild(params: CreateGuildParams): Promise<{ transactionHash: string }>; + registerAddresses(addresses: WireGuildAddressesParams): WireGuildAddressesParams; + resolveGuildAddresses(guildAddress: StarknetAddress): Promise; + governanceAction(params: GovernanceActionParams): Promise<{ transactionHash: string }>; + vote(params: VoteParams): Promise<{ transactionHash: string }>; + treasuryAction(params: TreasuryActionParams): Promise<{ transactionHash: string }>; + buyShares(params: ShareActionParams): Promise<{ transactionHash: string }>; + redeemShares(params: ShareActionParams): Promise<{ transactionHash: string }>; +} + +export class DefaultGuildsClient implements GuildsClient { + public readonly network: GuildsNetwork; + public readonly addresses: { + factory: StarknetAddress | undefined; + guildTemplate: StarknetAddress | undefined; + tokenTemplate: StarknetAddress | undefined; + governorTemplate: StarknetAddress | undefined; + }; + + private readonly transport: ContractTransport; + private readonly retry: GuildsClientOptions['retry']; + private readonly factory: FactoryBindings; + private readonly guild: GuildBindings; + + public constructor(transport: ContractTransport, options: GuildsClientOptions) { + this.transport = transport; + this.factory = createFactoryBindings(this.transport); + this.guild = createGuildBindings(this.transport); + this.network = options.network; + this.retry = options.retry; + + const defaults = DEFAULT_NETWORK_ADDRESSES[options.network] ?? {}; + this.addresses = { + factory: options.addresses?.factory ?? defaults.factory, + guildTemplate: options.addresses?.guildTemplate ?? defaults.guildTemplate, + tokenTemplate: options.addresses?.tokenTemplate ?? defaults.tokenTemplate, + governorTemplate: options.addresses?.governorTemplate ?? defaults.governorTemplate, + }; + } + + public async createGuild(params: CreateGuildParams): Promise<{ transactionHash: string }> { + const factory = this.requireFactoryAddress(); + this.validateCreateGuildParams(params); + + return withRetry( + 'createGuild', + async () => this.factory.createGuild(factory, params), + this.retry, + ).catch((error: unknown) => { + throw toGuildsSdkError(error, 'CONTRACT_CALL_FAILED'); + }); + } + + public registerAddresses(addresses: WireGuildAddressesParams): WireGuildAddressesParams { + assertAddress(addresses.guild, 'guild'); + assertAddress(addresses.token, 'token'); + assertAddress(addresses.governor, 'governor'); + return wireAddresses(addresses); + } + + public async resolveGuildAddresses(guildAddress: StarknetAddress): Promise { + const factory = this.requireFactoryAddress(); + return withRetry('resolveGuildAddresses', async () => { + const raw = await this.factory.getGuild(factory, guildAddress); + return decodeGuildAddresses(raw); + }, this.retry).catch((error: unknown) => { + throw toGuildsSdkError(error, 'CONTRACT_CALL_FAILED'); + }); + } + + public async governanceAction(params: GovernanceActionParams): Promise<{ transactionHash: string }> { + return withRetry('governanceAction', async () => this.guild.propose(params), this.retry).catch( + (error: unknown) => { + throw toGuildsSdkError(error, 'CONTRACT_CALL_FAILED'); + }, + ); + } + + public async vote(params: VoteParams): Promise<{ transactionHash: string }> { + return withRetry('vote', async () => this.guild.vote(params), this.retry).catch((error: unknown) => { + throw toGuildsSdkError(error, 'CONTRACT_CALL_FAILED'); + }); + } + + public async treasuryAction(params: TreasuryActionParams): Promise<{ transactionHash: string }> { + return withRetry('treasuryAction', async () => this.guild.executeCoreAction(params), this.retry).catch( + (error: unknown) => { + throw toGuildsSdkError(error, 'CONTRACT_CALL_FAILED'); + }, + ); + } + + public async buyShares(params: ShareActionParams): Promise<{ transactionHash: string }> { + return withRetry('buyShares', async () => this.guild.buyShares(params), this.retry).catch( + (error: unknown) => { + throw toGuildsSdkError(error, 'CONTRACT_CALL_FAILED'); + }, + ); + } + + public async redeemShares(params: ShareActionParams): Promise<{ transactionHash: string }> { + return withRetry('redeemShares', async () => this.guild.redeemShares(params), this.retry).catch( + (error: unknown) => { + throw toGuildsSdkError(error, 'CONTRACT_CALL_FAILED'); + }, + ); + } + + private requireFactoryAddress(): StarknetAddress { + const configured = this.addresses.factory; + const fallback = DEFAULT_NETWORK_ADDRESSES[this.network]?.factory; + const factory = configured ?? fallback; + if (!factory) { + throw new GuildsSdkError( + 'MISSING_ADDRESS', + `Missing factory address for network '${this.network}'. Provide options.addresses.factory.`, + ); + } + return assertAddress(factory, 'factory'); + } + + private validateCreateGuildParams(params: CreateGuildParams): void { + if (!params.name || !params.ticker) { + throw new GuildsSdkError('INVALID_INPUT', 'name and ticker are required'); + } + assertAddress(params.depositToken, 'depositToken'); + if (params.depositAmount < 0n || params.initialTokenSupply < 0n) { + throw new GuildsSdkError('INVALID_INPUT', 'depositAmount and initialTokenSupply must be >= 0'); + } + } +} diff --git a/sdk/src/client/index.ts b/sdk/src/client/index.ts new file mode 100644 index 0000000..32a3a8c --- /dev/null +++ b/sdk/src/client/index.ts @@ -0,0 +1,2 @@ +export * from './create-client.js'; +export * from './guilds-client.js'; diff --git a/sdk/src/config/index.ts b/sdk/src/config/index.ts new file mode 100644 index 0000000..3e553a9 --- /dev/null +++ b/sdk/src/config/index.ts @@ -0,0 +1 @@ +export * from './networks.js'; diff --git a/sdk/src/config/networks.ts b/sdk/src/config/networks.ts new file mode 100644 index 0000000..0bdb57e --- /dev/null +++ b/sdk/src/config/networks.ts @@ -0,0 +1,7 @@ +import type { NetworkAddressBook, GuildsNetwork } from '../types/network.js'; + +export const DEFAULT_NETWORK_ADDRESSES: Record = { + mainnet: {}, + sepolia: {}, + local: {}, +}; diff --git a/sdk/src/core/index.ts b/sdk/src/core/index.ts new file mode 100644 index 0000000..d2182e0 --- /dev/null +++ b/sdk/src/core/index.ts @@ -0,0 +1 @@ +export * from './transport.js'; diff --git a/sdk/src/core/transport.ts b/sdk/src/core/transport.ts new file mode 100644 index 0000000..7655f1b --- /dev/null +++ b/sdk/src/core/transport.ts @@ -0,0 +1,14 @@ +export interface CallRequest { + contractAddress: string; + entrypoint: string; + calldata: readonly string[]; +} + +export interface InvokeRequest extends CallRequest { + maxFee?: bigint; +} + +export interface ContractTransport { + call(request: CallRequest): Promise; + invoke(request: InvokeRequest): Promise<{ transactionHash: string }>; +} diff --git a/sdk/src/errors/index.ts b/sdk/src/errors/index.ts new file mode 100644 index 0000000..95d30d1 --- /dev/null +++ b/sdk/src/errors/index.ts @@ -0,0 +1,28 @@ +export type GuildsSdkErrorCode = + | 'INVALID_INPUT' + | 'NETWORK_MISMATCH' + | 'MISSING_ADDRESS' + | 'TRANSPORT_ERROR' + | 'CONTRACT_CALL_FAILED' + | 'RETRY_EXHAUSTED' + | 'CONFIG_ERROR'; + +export class GuildsSdkError extends Error { + public readonly code: GuildsSdkErrorCode; + public readonly details?: unknown; + + public constructor(code: GuildsSdkErrorCode, message: string, details?: unknown) { + super(message); + this.name = 'GuildsSdkError'; + this.code = code; + this.details = details; + } +} + +export function toGuildsSdkError(error: unknown, fallback: GuildsSdkErrorCode): GuildsSdkError { + if (error instanceof GuildsSdkError) { + return error; + } + const message = error instanceof Error ? error.message : 'Unknown SDK error'; + return new GuildsSdkError(fallback, message, error); +} diff --git a/sdk/src/index.ts b/sdk/src/index.ts new file mode 100644 index 0000000..65f9543 --- /dev/null +++ b/sdk/src/index.ts @@ -0,0 +1,7 @@ +export * from './client/index.js'; +export * from './bindings/index.js'; +export * from './core/index.js'; +export * from './types/index.js'; +export * from './utils/index.js'; +export * from './errors/index.js'; +export * from './config/index.js'; diff --git a/sdk/src/types/contracts.ts b/sdk/src/types/contracts.ts new file mode 100644 index 0000000..fdcea96 --- /dev/null +++ b/sdk/src/types/contracts.ts @@ -0,0 +1,60 @@ +export type StarknetAddress = `0x${string}`; + +export type BigNumberish = bigint | number | string; + +export interface GovernorConfig { + votingDelay: bigint; + votingPeriod: bigint; + proposalThreshold: bigint; + quorumBps: number; + timelockDelay: bigint; +} + +export interface CreateGuildParams { + name: string; + ticker: string; + depositToken: StarknetAddress; + depositAmount: bigint; + initialTokenSupply: bigint; + governorConfig: GovernorConfig; +} + +export interface GuildAddresses { + guild: StarknetAddress; + token: StarknetAddress; + governor: StarknetAddress; +} + +export interface WireGuildAddressesParams { + guild: StarknetAddress; + token: StarknetAddress; + governor: StarknetAddress; +} + +export interface GovernanceActionParams { + governor: StarknetAddress; + targets: StarknetAddress[]; + values: bigint[]; + calldatas: string[]; + description: string; +} + +export interface VoteParams { + governor: StarknetAddress; + proposalId: bigint; + support: 0 | 1 | 2; +} + +export interface TreasuryActionParams { + guild: StarknetAddress; + actionType: number; + target: StarknetAddress; + token: StarknetAddress; + amount: bigint; + calldata: string[]; +} + +export interface ShareActionParams { + guild: StarknetAddress; + amount: bigint; +} diff --git a/sdk/src/types/index.ts b/sdk/src/types/index.ts new file mode 100644 index 0000000..10d4079 --- /dev/null +++ b/sdk/src/types/index.ts @@ -0,0 +1,2 @@ +export * from './contracts.js'; +export * from './network.js'; diff --git a/sdk/src/types/network.ts b/sdk/src/types/network.ts new file mode 100644 index 0000000..79ba9a4 --- /dev/null +++ b/sdk/src/types/network.ts @@ -0,0 +1,21 @@ +import type { StarknetAddress } from './contracts.js'; + +export type GuildsNetwork = 'mainnet' | 'sepolia' | 'local'; + +export interface NetworkAddressBook { + factory?: StarknetAddress; + guildTemplate?: StarknetAddress; + tokenTemplate?: StarknetAddress; + governorTemplate?: StarknetAddress; +} + +export interface GuildsClientOptions { + network: GuildsNetwork; + addresses?: NetworkAddressBook; + retry?: { + attempts?: number; + initialDelayMs?: number; + maxDelayMs?: number; + backoffMultiplier?: number; + }; +} diff --git a/sdk/src/utils/address.ts b/sdk/src/utils/address.ts new file mode 100644 index 0000000..028889f --- /dev/null +++ b/sdk/src/utils/address.ts @@ -0,0 +1,13 @@ +import { GuildsSdkError } from '../errors/index.js'; +import type { StarknetAddress } from '../types/contracts.js'; + +export function isHexAddress(value: string): value is StarknetAddress { + return /^0x[0-9a-fA-F]+$/.test(value) && value.length >= 4; +} + +export function assertAddress(value: string, fieldName: string): StarknetAddress { + if (!isHexAddress(value)) { + throw new GuildsSdkError('INVALID_INPUT', `Invalid address for ${fieldName}: ${value}`); + } + return value; +} diff --git a/sdk/src/utils/index.ts b/sdk/src/utils/index.ts new file mode 100644 index 0000000..40db050 --- /dev/null +++ b/sdk/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './address.js'; +export * from './retry.js'; diff --git a/sdk/src/utils/retry.ts b/sdk/src/utils/retry.ts new file mode 100644 index 0000000..452caad --- /dev/null +++ b/sdk/src/utils/retry.ts @@ -0,0 +1,49 @@ +import { GuildsSdkError, toGuildsSdkError } from '../errors/index.js'; + +export interface RetryOptions { + attempts: number; + initialDelayMs: number; + maxDelayMs: number; + backoffMultiplier: number; + retryableError?: (error: unknown) => boolean; +} + +export const DEFAULT_RETRY_OPTIONS: RetryOptions = { + attempts: 3, + initialDelayMs: 150, + maxDelayMs: 1_000, + backoffMultiplier: 2, + retryableError: () => true, +}; + +export async function withRetry( + operationName: string, + fn: () => Promise, + options: Partial = {}, +): Promise { + const cfg: RetryOptions = { ...DEFAULT_RETRY_OPTIONS, ...options }; + let lastError: unknown; + for (let attempt = 1; attempt <= cfg.attempts; attempt += 1) { + try { + return await fn(); + } catch (error) { + lastError = error; + const retryable = cfg.retryableError?.(error) ?? false; + if (!retryable || attempt === cfg.attempts) { + break; + } + const delay = Math.min( + cfg.maxDelayMs, + Math.round(cfg.initialDelayMs * cfg.backoffMultiplier ** (attempt - 1)), + ); + await new Promise((resolve) => { + setTimeout(resolve, delay); + }); + } + } + throw new GuildsSdkError( + 'RETRY_EXHAUSTED', + `Operation '${operationName}' failed after ${cfg.attempts} attempts`, + toGuildsSdkError(lastError, 'TRANSPORT_ERROR'), + ); +} diff --git a/sdk/tsconfig.build.json b/sdk/tsconfig.build.json new file mode 100644 index 0000000..4b1c236 --- /dev/null +++ b/sdk/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "types": ["node"] + }, + "include": ["src/**/*.ts"], + "exclude": ["tests", "dist", "node_modules"] +} diff --git a/sdk/tsconfig.examples.json b/sdk/tsconfig.examples.json new file mode 100644 index 0000000..a5d7403 --- /dev/null +++ b/sdk/tsconfig.examples.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": ".", + "noEmit": true + }, + "include": ["src/**/*.ts", "examples/**/*.ts"], + "exclude": ["dist", "node_modules", "tests"] +} diff --git a/sdk/tsconfig.json b/sdk/tsconfig.json new file mode 100644 index 0000000..0a5d87d --- /dev/null +++ b/sdk/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "lib": ["ES2022"], + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + "declaration": true, + "sourceMap": true, + "outDir": "dist", + "rootDir": ".", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "types": ["vitest/globals", "node"] + }, + "include": ["src/**/*.ts", "tests/**/*.ts"], + "exclude": ["dist", "node_modules"] +}