feat: add stxer simulation

This commit is contained in:
Kyle Fang
2024-09-19 10:41:24 +00:00
parent c7b6027d74
commit 284e269bb4
4 changed files with 691 additions and 19 deletions

View File

@@ -11,15 +11,20 @@
"dependencies": {
"@stacks/connect": "^7.2.1",
"@stacks/network": "^6.10.0",
"@stacks/stacks-blockchain-api-types": "^7.14.1",
"@stacks/transactions": "^6.16.1",
"alex-sdk": "^2.1.4",
"c32check": "^2.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"ts-clarity": "^0.0.26"
},
"devDependencies": {
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@vitejs/plugin-react": "^4.3.1",
"prettier": "^3.3.2",
"tsx": "^4.19.1",
"typescript": "^5.4.5",
"vite": "^5.3.1"
}

375
pnpm-lock.yaml generated
View File

@@ -14,15 +14,27 @@ importers:
'@stacks/network':
specifier: ^6.10.0
version: 6.10.0
'@stacks/stacks-blockchain-api-types':
specifier: ^7.14.1
version: 7.14.1
'@stacks/transactions':
specifier: ^6.16.1
version: 6.16.1
alex-sdk:
specifier: ^2.1.4
version: 2.1.4(@stacks/network@6.10.0)(@stacks/transactions@6.9.0)
version: 2.1.4(@stacks/network@6.10.0)(@stacks/transactions@6.16.1)
c32check:
specifier: ^2.0.0
version: 2.0.0
react:
specifier: ^18.2.0
version: 18.2.0
react-dom:
specifier: ^18.2.0
version: 18.2.0(react@18.2.0)
ts-clarity:
specifier: ^0.0.26
version: 0.0.26(typescript@5.4.5)
devDependencies:
'@types/react':
specifier: ^18.0.27
@@ -36,6 +48,9 @@ importers:
prettier:
specifier: ^3.3.2
version: 3.3.2
tsx:
specifier: ^4.19.1
version: 4.19.1
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -175,138 +190,282 @@ packages:
cpu: [ppc64]
os: [aix]
'@esbuild/aix-ppc64@0.23.1':
resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.21.5':
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm64@0.23.1':
resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.21.5':
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
'@esbuild/android-arm@0.23.1':
resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.21.5':
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
'@esbuild/android-x64@0.23.1':
resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.21.5':
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-arm64@0.23.1':
resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.21.5':
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
'@esbuild/darwin-x64@0.23.1':
resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.21.5':
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-arm64@0.23.1':
resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.21.5':
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
'@esbuild/freebsd-x64@0.23.1':
resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.21.5':
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm64@0.23.1':
resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.21.5':
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
'@esbuild/linux-arm@0.23.1':
resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.21.5':
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-ia32@0.23.1':
resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.21.5':
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-loong64@0.23.1':
resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.21.5':
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-mips64el@0.23.1':
resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.21.5':
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-ppc64@0.23.1':
resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.21.5':
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-riscv64@0.23.1':
resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.21.5':
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-s390x@0.23.1':
resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.21.5':
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
'@esbuild/linux-x64@0.23.1':
resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/netbsd-x64@0.21.5':
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
'@esbuild/netbsd-x64@0.23.1':
resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.23.1':
resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.21.5':
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
'@esbuild/openbsd-x64@0.23.1':
resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/sunos-x64@0.21.5':
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
'@esbuild/sunos-x64@0.23.1':
resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.21.5':
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-arm64@0.23.1':
resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.21.5':
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-ia32@0.23.1':
resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.21.5':
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
'@esbuild/win32-x64@0.23.1':
resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@jridgewell/gen-mapping@0.3.3':
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
engines: {node: '>=6.0.0'}
@@ -438,6 +597,9 @@ packages:
'@stacks/common@6.10.0':
resolution: {integrity: sha512-6x5Z7AKd9/kj3+DYE9xIDIkFLHihBH614i2wqrZIjN02WxVo063hWSjIlUxlx8P4gl6olVzlOy5LzhLJD9OP0A==}
'@stacks/common@6.16.0':
resolution: {integrity: sha512-PnzvhrdGRMVZvxTulitlYafSK4l02gPCBBoI9QEoTqgSnv62oaOXhYAUUkTMFKxdHW1seVEwZsrahuXiZPIAwg==}
'@stacks/common@6.8.1':
resolution: {integrity: sha512-ewL9GLZNQYa5a/3K4xSHlHIgHkD4rwWW/QEaPId8zQIaL+1O9qCaF4LX9orNQeOmEk8kvG0x2xGV54fXKCZeWQ==}
@@ -453,14 +615,17 @@ packages:
'@stacks/network@6.10.0':
resolution: {integrity: sha512-mbiZ8nlsyy77ndmBdaqhHXii22IFdK4ThRcOQs9j/O00DkAr04jCM4GV5Q+VLUnZ9OBoJq7yOV7Pf6jglh+0hw==}
'@stacks/network@6.16.0':
resolution: {integrity: sha512-uqz9Nb6uf+SeyCKENJN+idt51HAfEeggQKrOMfGjpAeFgZV2CR66soB/ci9+OVQR/SURvasncAz2ScI1blfS8A==}
'@stacks/profile@6.9.0':
resolution: {integrity: sha512-sIR60DsAHi8C6zGqKqSe1r2hXTMHgwrJkX3fAaP3de40KeplZ2bkE+0B83yismEeU2baNc+AukyVvWJv0PfP0A==}
'@stacks/stacks-blockchain-api-types@7.3.2':
resolution: {integrity: sha512-1r0+eqEWOOo7UYrFq9HGbc02DVME3NVCW/45sNKPN31PkOMMaK59DHragPJ2QbxPFiutVDUCS924+48+o3+0Tw==}
'@stacks/stacks-blockchain-api-types@7.14.1':
resolution: {integrity: sha512-65hvhXxC+EUqHJAQsqlBCqXB+zwfxZICSKYJugdg6BCp9I9qniyfz5XyQeC4RMVo0tgEoRdS/b5ZCFo5kLWmxA==}
'@stacks/transactions@6.9.0':
resolution: {integrity: sha512-hSs9+0Ew++GwMZMgPObOx0iVCQRxkiCqI+DHdPEikAmg2utpyLh2/txHOjfSIkQHvcBfJJ6O5KphmxDP4gUqiA==}
'@stacks/transactions@6.16.1':
resolution: {integrity: sha512-yCtUM+8IN0QJbnnlFhY1wBW7Q30Cxje3Zmy8DgqdBoM/EPPWadez/8wNWFANVAMyUZeQ9V/FY+8MAw4E+pCReA==}
'@stencil/core@2.22.3':
resolution: {integrity: sha512-kmVA0M/HojwsfkeHsifvHVIYe4l5tin7J5+DLgtl8h6WWfiMClND5K3ifCXXI2ETDNKiEk21p6jql3Fx9o2rng==}
@@ -562,6 +727,14 @@ packages:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
clarity-abi@0.0.20:
resolution: {integrity: sha512-uAkKEp84Z3LnM8qruLJyB1LP2NEGwns6Sl6zBOiKeIgTfFMm3GrQlTgkFUboVV/RQwk0dJYc72sV8pvSrtn+Sg==}
peerDependencies:
typescript: '>=5.0.4'
peerDependenciesMeta:
typescript:
optional: true
clarity-codegen@0.5.2:
resolution: {integrity: sha512-t0uvboeZTII7n2lgobAxcQnhyjXwbUKYdUKJA3yjoaOXPvtr5i2zFV7H1E6ZeDMfqd3vIksMPvpdFfXum9SoNQ==}
hasBin: true
@@ -595,6 +768,9 @@ packages:
cross-fetch@3.1.8:
resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==}
cross-fetch@4.0.0:
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
csstype@3.1.2:
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
@@ -622,6 +798,11 @@ packages:
engines: {node: '>=12'}
hasBin: true
esbuild@0.23.1:
resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
engines: {node: '>=18'}
hasBin: true
escalade@3.1.2:
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
engines: {node: '>=6'}
@@ -662,6 +843,9 @@ packages:
get-intrinsic@1.2.1:
resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
get-tsconfig@4.8.1:
resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
globals@11.12.0:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
@@ -788,6 +972,9 @@ packages:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
ripemd160-min@0.0.6:
resolution: {integrity: sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==}
engines: {node: '>=8'}
@@ -836,6 +1023,14 @@ packages:
tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
ts-clarity@0.0.26:
resolution: {integrity: sha512-XRwLquuSTDkw6iYEpznMEEgehqaIR9t313chiiZTfvtRCq/kWYXPHQhgdTw6wJBAHsqdVPuN69enwlKtu2IQPg==}
tsx@4.19.1:
resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==}
engines: {node: '>=18.0.0'}
hasBin: true
typescript@5.4.5:
resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
engines: {node: '>=14.17'}
@@ -1082,72 +1277,144 @@ snapshots:
'@esbuild/aix-ppc64@0.21.5':
optional: true
'@esbuild/aix-ppc64@0.23.1':
optional: true
'@esbuild/android-arm64@0.21.5':
optional: true
'@esbuild/android-arm64@0.23.1':
optional: true
'@esbuild/android-arm@0.21.5':
optional: true
'@esbuild/android-arm@0.23.1':
optional: true
'@esbuild/android-x64@0.21.5':
optional: true
'@esbuild/android-x64@0.23.1':
optional: true
'@esbuild/darwin-arm64@0.21.5':
optional: true
'@esbuild/darwin-arm64@0.23.1':
optional: true
'@esbuild/darwin-x64@0.21.5':
optional: true
'@esbuild/darwin-x64@0.23.1':
optional: true
'@esbuild/freebsd-arm64@0.21.5':
optional: true
'@esbuild/freebsd-arm64@0.23.1':
optional: true
'@esbuild/freebsd-x64@0.21.5':
optional: true
'@esbuild/freebsd-x64@0.23.1':
optional: true
'@esbuild/linux-arm64@0.21.5':
optional: true
'@esbuild/linux-arm64@0.23.1':
optional: true
'@esbuild/linux-arm@0.21.5':
optional: true
'@esbuild/linux-arm@0.23.1':
optional: true
'@esbuild/linux-ia32@0.21.5':
optional: true
'@esbuild/linux-ia32@0.23.1':
optional: true
'@esbuild/linux-loong64@0.21.5':
optional: true
'@esbuild/linux-loong64@0.23.1':
optional: true
'@esbuild/linux-mips64el@0.21.5':
optional: true
'@esbuild/linux-mips64el@0.23.1':
optional: true
'@esbuild/linux-ppc64@0.21.5':
optional: true
'@esbuild/linux-ppc64@0.23.1':
optional: true
'@esbuild/linux-riscv64@0.21.5':
optional: true
'@esbuild/linux-riscv64@0.23.1':
optional: true
'@esbuild/linux-s390x@0.21.5':
optional: true
'@esbuild/linux-s390x@0.23.1':
optional: true
'@esbuild/linux-x64@0.21.5':
optional: true
'@esbuild/linux-x64@0.23.1':
optional: true
'@esbuild/netbsd-x64@0.21.5':
optional: true
'@esbuild/netbsd-x64@0.23.1':
optional: true
'@esbuild/openbsd-arm64@0.23.1':
optional: true
'@esbuild/openbsd-x64@0.21.5':
optional: true
'@esbuild/openbsd-x64@0.23.1':
optional: true
'@esbuild/sunos-x64@0.21.5':
optional: true
'@esbuild/sunos-x64@0.23.1':
optional: true
'@esbuild/win32-arm64@0.21.5':
optional: true
'@esbuild/win32-arm64@0.23.1':
optional: true
'@esbuild/win32-ia32@0.21.5':
optional: true
'@esbuild/win32-ia32@0.23.1':
optional: true
'@esbuild/win32-x64@0.21.5':
optional: true
'@esbuild/win32-x64@0.23.1':
optional: true
'@jridgewell/gen-mapping@0.3.3':
dependencies:
'@jridgewell/set-array': 1.1.2
@@ -1255,6 +1522,11 @@ snapshots:
'@types/bn.js': 5.1.2
'@types/node': 18.18.4
'@stacks/common@6.16.0':
dependencies:
'@types/bn.js': 5.1.2
'@types/node': 18.18.4
'@stacks/common@6.8.1':
dependencies:
'@types/bn.js': 5.1.2
@@ -1270,7 +1542,7 @@ snapshots:
'@stacks/connect-ui': 6.0.1
'@stacks/network': 6.10.0
'@stacks/profile': 6.9.0
'@stacks/transactions': 6.9.0
'@stacks/transactions': 6.16.1
jsontokens: 4.0.1
url: 0.11.3
transitivePeerDependencies:
@@ -1295,25 +1567,32 @@ snapshots:
transitivePeerDependencies:
- encoding
'@stacks/network@6.16.0':
dependencies:
'@stacks/common': 6.16.0
cross-fetch: 3.1.8
transitivePeerDependencies:
- encoding
'@stacks/profile@6.9.0':
dependencies:
'@stacks/common': 6.8.1
'@stacks/network': 6.10.0
'@stacks/transactions': 6.9.0
'@stacks/transactions': 6.16.1
jsontokens: 4.0.1
schema-inspector: 2.1.0
zone-file: 2.0.0-beta.3
transitivePeerDependencies:
- encoding
'@stacks/stacks-blockchain-api-types@7.3.2': {}
'@stacks/stacks-blockchain-api-types@7.14.1': {}
'@stacks/transactions@6.9.0':
'@stacks/transactions@6.16.1':
dependencies:
'@noble/hashes': 1.1.5
'@noble/secp256k1': 1.7.1
'@stacks/common': 6.8.1
'@stacks/network': 6.10.0
'@stacks/common': 6.16.0
'@stacks/network': 6.16.0
c32check: 2.0.0
lodash.clonedeep: 4.5.0
transitivePeerDependencies:
@@ -1375,11 +1654,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
alex-sdk@2.1.4(@stacks/network@6.10.0)(@stacks/transactions@6.9.0):
alex-sdk@2.1.4(@stacks/network@6.10.0)(@stacks/transactions@6.16.1):
dependencies:
'@stacks/network': 6.10.0
'@stacks/transactions': 6.9.0
clarity-codegen: 0.5.2(@stacks/transactions@6.9.0)
'@stacks/transactions': 6.16.1
clarity-codegen: 0.5.2(@stacks/transactions@6.16.1)
transitivePeerDependencies:
- debug
@@ -1424,7 +1703,7 @@ snapshots:
c32check@2.0.0:
dependencies:
'@noble/hashes': 1.1.5
'@noble/hashes': 1.3.2
base-x: 4.0.0
call-bind@1.0.2:
@@ -1440,10 +1719,14 @@ snapshots:
escape-string-regexp: 1.0.5
supports-color: 5.5.0
clarity-codegen@0.5.2(@stacks/transactions@6.9.0):
clarity-abi@0.0.20(typescript@5.4.5):
optionalDependencies:
typescript: 5.4.5
clarity-codegen@0.5.2(@stacks/transactions@6.16.1):
dependencies:
'@stacks/stacks-blockchain-api-types': 7.3.2
'@stacks/transactions': 6.9.0
'@stacks/stacks-blockchain-api-types': 7.14.1
'@stacks/transactions': 6.16.1
axios: 1.7.2
lodash: 4.17.21
yargs: 17.7.2
@@ -1481,6 +1764,12 @@ snapshots:
transitivePeerDependencies:
- encoding
cross-fetch@4.0.0:
dependencies:
node-fetch: 2.7.0
transitivePeerDependencies:
- encoding
csstype@3.1.2: {}
debug@4.3.4:
@@ -1519,6 +1808,33 @@ snapshots:
'@esbuild/win32-ia32': 0.21.5
'@esbuild/win32-x64': 0.21.5
esbuild@0.23.1:
optionalDependencies:
'@esbuild/aix-ppc64': 0.23.1
'@esbuild/android-arm': 0.23.1
'@esbuild/android-arm64': 0.23.1
'@esbuild/android-x64': 0.23.1
'@esbuild/darwin-arm64': 0.23.1
'@esbuild/darwin-x64': 0.23.1
'@esbuild/freebsd-arm64': 0.23.1
'@esbuild/freebsd-x64': 0.23.1
'@esbuild/linux-arm': 0.23.1
'@esbuild/linux-arm64': 0.23.1
'@esbuild/linux-ia32': 0.23.1
'@esbuild/linux-loong64': 0.23.1
'@esbuild/linux-mips64el': 0.23.1
'@esbuild/linux-ppc64': 0.23.1
'@esbuild/linux-riscv64': 0.23.1
'@esbuild/linux-s390x': 0.23.1
'@esbuild/linux-x64': 0.23.1
'@esbuild/netbsd-x64': 0.23.1
'@esbuild/openbsd-arm64': 0.23.1
'@esbuild/openbsd-x64': 0.23.1
'@esbuild/sunos-x64': 0.23.1
'@esbuild/win32-arm64': 0.23.1
'@esbuild/win32-ia32': 0.23.1
'@esbuild/win32-x64': 0.23.1
escalade@3.1.2: {}
escape-string-regexp@1.0.5: {}
@@ -1547,6 +1863,10 @@ snapshots:
has-proto: 1.0.1
has-symbols: 1.0.3
get-tsconfig@4.8.1:
dependencies:
resolve-pkg-maps: 1.0.0
globals@11.12.0: {}
has-flag@3.0.0: {}
@@ -1635,6 +1955,8 @@ snapshots:
require-directory@2.1.1: {}
resolve-pkg-maps@1.0.0: {}
ripemd160-min@0.0.6: {}
rollup@4.18.0:
@@ -1697,6 +2019,23 @@ snapshots:
tr46@0.0.3: {}
ts-clarity@0.0.26(typescript@5.4.5):
dependencies:
'@stacks/stacks-blockchain-api-types': 7.14.1
'@stacks/transactions': 6.16.1
clarity-abi: 0.0.20(typescript@5.4.5)
cross-fetch: 4.0.0
transitivePeerDependencies:
- encoding
- typescript
tsx@4.19.1:
dependencies:
esbuild: 0.23.1
get-tsconfig: 4.8.1
optionalDependencies:
fsevents: 2.3.3
typescript@5.4.5: {}
update-browserslist-db@1.0.16(browserslist@4.23.1):

15
simulation/index.ts Normal file
View File

@@ -0,0 +1,15 @@
import { AlexSDK, Currency } from "alex-sdk";
import { SimulationBuilder } from "./stxer";
const sdk = new AlexSDK()
const addr = "SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER"
const tx = await sdk.runSwap(addr, Currency.STX, Currency.ALEX, BigInt(1e8), 0n)
await SimulationBuilder.new()
.withSender(addr)
.addContractCall({
contract_id: `${tx.contractAddress}.${tx.contractName}`,
function_name: tx.functionName,
function_args: tx.functionArgs
})
.run()

313
simulation/stxer.ts Normal file
View File

@@ -0,0 +1,313 @@
import { AccountDataResponse, getNodeInfo, richFetch } from 'ts-clarity';
import { Block } from '@stacks/stacks-blockchain-api-types';
import { StacksMainnet } from '@stacks/network';
import {
AnchorMode,
ClarityValue,
PostConditionMode,
type StacksTransaction,
bufferCV,
contractPrincipalCV,
makeUnsignedContractCall,
makeUnsignedContractDeploy,
makeUnsignedSTXTokenTransfer,
serializeCV,
stringAsciiCV,
tupleCV,
uintCV,
} from '@stacks/transactions';
import { c32addressDecode } from 'c32check';
// current beta api endpoint
const SIMULATION_API_ENDPOINT = 'https://api.stxer.xyz/simulations';
function runTx(tx: StacksTransaction) {
// type 0: run transaction
return tupleCV({ type: uintCV(0), data: bufferCV(tx.serialize()) });
}
export interface SimulationEval {
contract_id: string;
code: string;
}
export function runEval({ contract_id, code }: SimulationEval) {
const [contract_address, contract_name] = contract_id.split('.');
// type 1: eval arbitrary code inside a contract
return tupleCV({
type: uintCV(1),
data: bufferCV(
serializeCV(
tupleCV({
contract: contractPrincipalCV(contract_address, contract_name),
code: stringAsciiCV(code),
})
)
),
});
}
export async function runSimulation(
block_hash: string,
block_height: number,
txs: (StacksTransaction | SimulationEval)[]
) {
const body = Buffer.concat([
Buffer.from('sim-v1'),
Buffer.alloc(8),
Buffer.from(
block_hash.startsWith('0x') ? block_hash.substring(2) : block_hash,
'hex'
),
...txs
.map((t) => {
return 'contract_id' in t && 'code' in t ? runEval(t) : runTx(t);
})
.map((t) => serializeCV(t)),
]);
body.writeBigUInt64BE(BigInt(block_height), 6);
const rs = await fetch(SIMULATION_API_ENDPOINT, {
method: 'POST',
body,
}).then(async (rs) => {
const response = await rs.text();
if (!response.startsWith('{')) {
throw new Error(`failed to submit simulation: ${response}`);
}
// console.log(response);
return JSON.parse(response) as { id: string };
});
return rs.id;
}
export class SimulationBuilder {
public static new() {
return new SimulationBuilder();
}
private block = NaN;
private sender = '';
private steps: (
| {
// contract call
contract_id: string;
function_name: string;
function_args?: ClarityValue[];
sender: string;
fee: number;
}
| {
// contract deploy
contract_name: string;
source_code: string;
deployer: string;
fee: number;
}
| {
// STX transfer
recipient: string;
amount: number;
sender: string;
fee: number;
}
| SimulationEval
)[] = [];
public useBlockHeight(block: number) {
this.block = block;
return this;
}
public withSender(address: string) {
this.sender = address;
return this;
}
public addSTXTransfer(params: {
recipient: string;
amount: number;
sender?: string;
fee?: number;
}) {
if (params.sender == null && this.sender === '') {
throw new Error(
'Please specify a sender with useSender or adding a sender paramenter'
);
}
this.steps.push({
...params,
sender: params.sender ?? this.sender,
fee: params.fee ?? 0,
});
return this;
}
public addContractCall(params: {
contract_id: string;
function_name: string;
function_args?: ClarityValue[];
sender?: string;
fee?: number;
}) {
if (params.sender == null && this.sender === '') {
throw new Error(
'Please specify a sender with useSender or adding a sender paramenter'
);
}
this.steps.push({
...params,
sender: params.sender ?? this.sender,
fee: params.fee ?? 0,
});
return this;
}
public addContractDeploy(params: {
contract_name: string;
source_code: string;
deployer?: string;
fee?: number;
}) {
if (params.deployer == null && this.sender === '') {
throw new Error(
'Please specify a deployer with useSender or adding a deployer paramenter'
);
}
this.steps.push({
...params,
deployer: params.deployer ?? this.sender,
fee: params.fee ?? 0,
});
return this;
}
public addEvalCode(inside_contract_id: string, code: string) {
this.steps.push({
contract_id: inside_contract_id,
code,
});
return this;
}
public addMapRead(contract_id: string, map: string, key: string) {
this.steps.push({
contract_id,
code: `(map-get ${map} ${key})`,
});
return this;
}
public addVarRead(contract_id: string, variable: string) {
this.steps.push({
contract_id,
code: `(var-get ${variable})`,
});
return this;
}
private async getBlockInfo() {
if (Number.isNaN(this.block)) {
const { stacks_tip_height } = await getNodeInfo();
this.block = stacks_tip_height;
}
const info: Block = await richFetch(
`https://api.hiro.so/extended/v1/block/by_height/${this.block}?unanchored=true`
).then((r) => r.json());
if (
info.height !== this.block ||
typeof info.hash !== 'string' ||
!info.hash.startsWith('0x')
) {
throw new Error(
`failed to get block info for block height ${this.block}`
);
}
return {
block_height: this.block,
block_hash: info.hash.substring(2),
index_block_hash: info.index_block_hash.substring(2),
};
}
public async run() {
console.log(
`--------------------------------
This product can never exist without your support!
We receive sponsorship funds with:
SP212Y5JKN59YP3GYG07K3S8W5SSGE4KH6B5STXER
Feedbacks and feature requests are welcome.
To get in touch: contact@stxer.xyz
--------------------------------`
);
const block = await this.getBlockInfo();
console.log(
`Using block height ${block.block_height} hash 0x${block.block_hash} to run simulation.`
);
const txs: (StacksTransaction | SimulationEval)[] = [];
const nonce_by_address = new Map<string, number>();
const nextNonce = async (sender: string) => {
let nonce = nonce_by_address.get(sender);
if (nonce == null) {
const url = `https://api.hiro.so/v2/accounts/${sender}?proof=${false}&tip=${block.index_block_hash
}`;
const account: AccountDataResponse = await richFetch(url).then((r) =>
r.json()
);
nonce_by_address.set(sender, account.nonce + 1);
return account.nonce;
}
nonce_by_address.set(sender, nonce + 1);
return nonce;
};
for (const step of this.steps) {
if ('sender' in step && 'function_name' in step) {
const nonce = await nextNonce(step.sender);
const [contractAddress, contractName] = step.contract_id.split('.');
const tx = await makeUnsignedContractCall({
contractAddress,
contractName,
functionName: step.function_name,
functionArgs: step.function_args ?? [],
nonce,
network: new StacksMainnet(),
publicKey: '',
postConditionMode: PostConditionMode.Allow,
anchorMode: AnchorMode.Any,
fee: step.fee,
});
tx.auth.spendingCondition.signer = c32addressDecode(step.sender)[1];
txs.push(tx);
} else if ('sender' in step && 'recipient' in step) {
const nonce = await nextNonce(step.sender);
const tx = await makeUnsignedSTXTokenTransfer({
recipient: step.recipient,
amount: step.amount,
nonce,
network: new StacksMainnet(),
publicKey: '',
anchorMode: AnchorMode.Any,
fee: step.fee,
});
tx.auth.spendingCondition.signer = c32addressDecode(step.sender)[1];
txs.push(tx);
} else if ('deployer' in step) {
const nonce = await nextNonce(step.deployer);
const tx = await makeUnsignedContractDeploy({
contractName: step.contract_name,
codeBody: step.source_code,
nonce,
network: new StacksMainnet(),
publicKey: '',
postConditionMode: PostConditionMode.Allow,
anchorMode: AnchorMode.Any,
fee: step.fee,
});
tx.auth.spendingCondition.signer = c32addressDecode(step.deployer)[1];
txs.push(tx);
} else if ('code' in step) {
txs.push(step);
} else {
console.log(`Invalid simulation step:`, step);
}
}
const id = await runSimulation(block.block_hash, block.block_height, txs);
console.log(
`Simulation will be available at: https://stxer.xyz/simulations/mainnet/${id}`
);
return id;
}
}