mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-08-18 09:48:05 +00:00
Merge pull request #100 from chainstacklabs/feat/learning-examples-creator-fee
Add/update buy and sell transaction for PumpSwap
This commit is contained in:
+133
-273
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"transaction": [
|
"transaction": [
|
||||||
"AgJ5wlQKptQK5lR1rKuLex98aANgrofIxDKh4bYcGBMqRrxspLReufQPA/MY9iyOBRs9J9ZAJvcIpuUzlP8lRQYKgV5owXDiYc0bAtKwtbffRx+4AujjJwkjulgWBz/08YbOU0cmqeRb3AUlhjOE5TkvHJGGT6D7X77Jpbxh9soDgAIAChL2MdL3xlA70bgIpTlRVYJ5yU7c4gCGkVyzuRpXUJYvmr5Oab9+zoJi5E/7feiMCGSkHpgBjBAk2HT/Omepbi/vvCtXBl7x3WZUML5ga6ZZbAKVMBut74ta/EEBQVD0EnQ7v7zcho+rNAKa57FiZ8EqFb32kF/Udj9NCpqzDWcquz307oLnDRm67n4w0qFL1j/3+kqE89q4xc3YQSOLLomVa8GPpVJkRHOYFAgQ5WYKuVxAmb0NVDhLEkMsLPLU/zvJ9WOIIMD9HQRJCq0s/CX00AY27y+Miq5i8Ng5rck8jK0R5qT8KUSk+oJRvvgVQm4b+yjGtmRmd2B8atn1ZqZGAwZGb+UhFzL/7K26csOb57yM5bvF9xJrLEObOkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFW4PaTZlrPRNsVaL8XW6pRicuX9dL/O2VdK7b9bRiwBsXBzmONJWfSZGiwXrlR0aKNzG4SNIK1xnUUl3DmK/I6hl5p7g9UgMq89mNX5NwvGNWNRcHqdIn7NyPZeTxypgtwZbHj0XxFOJ1Sf2sEw81YuGxzGqD9tUm20bwD+ClGBt324ddloZPZy+FGzut5rBy0he1fWzeROoz1hX7/AKmMlyWPTiSJ8bs9ECkUjg2DC1oTmdr/EIQEjnvY2+n4WQan1RcZLFxRIYzJTD1K8X9Y2u4Im6H9ROPb2YoAAAAArPE26wH8HE6IPSPItYRKtZo39mrdV8XprDtT4FnTXGTKXRcVnMiLdm8v4gNxeTkclw+K5btmaK2siraOY9HdQAYIAAUCkNADAAkCAAIMAgAAAAAJPQAAAAAACAAJA6BoBgAAAAAACg4BCwMEDA0FAAkODxARCmEYHsgoBRwHdwMAAABkb2QDAAAARE9ERwAAAGh0dHBzOi8vY2YtaXBmcy5jb20vaXBmcy9RbVkxbTJvd2hqQlp6eTFNdGhZbVdpbjNYd0dpbUdLV0M1WndOWFBDYmJhQjFrDwYABgABCQ4ACgwMBwEDBAYACQ4QEQoYZgY9EgHa6+op661VhCIAAMCDOEIAAAAAAA==",
|
"AYqt4iSMLUKIiCn+roUn59P7c0BroL8VCv5X+0515tjH9d5OCez5MIQdftuWcDwEymBNZMWiqy51LDU76WpahAMBAAoTcFi8Lm3PgW7X4XZm7q8+G4Jf4IaSLzptQdkNfSFrd2kW7510gs4rvSfIQ6BD7SbUQJaGC396SVFLuDF387+XgV1pfIfVUZFTFHxe1tb+5NIGBoToM9rJFbh9akpqDSa8XwszrDDJuVPznYGftPUIqlfBd55SSEGIUQWL6ZogaoujB/IYgIAD1tGqXa268xcm661aIHELJcoHVKW8TJPIRaOJkcMpfWvPuYxyTGf253mdFudiJ5NiHvVmi0CTGjvCsU4N5V6fuoY5br/VSM/4ySAR6se3W6qbLZxqhvWhcUHXqo+wYNgpG0xNR12v92LJa9wNrOs2wBLq0S7TqUhBYfprphss/CT2/qy59h94SA3zpgqeFhalg6tebfEaQX2yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVuD2k2Zaz0TbFWi/F1uqUYnLl/XS/ztlXSu2/W0YsAMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAABt324ddloZPZy+FGzut5rBy0he1fWzeROoz1hX7/AKkG3fbh7nWP3hhCXbzkbM3athr8TYO5DSf+vfko2KGL/Ai2qPUzOEL8dkpbTkkIfplULeP8horDFNap3dmbsYVGOoZeae4PVIDKvPZjV+TcLxjVjUXB6nSJ+zcj2Xk8cqZE+dQlVubfmlZx8g4Yr7VZS6dIqY5CCXXxzYTAYMWwb4yXJY9OJInxuz0QKRSODYMLWhOZ2v8QhASOe9jb6fhZrPE26wH8HE6IPSPItYRKtZo39mrdV8XprDtT4FnTXGT58ypqlPJGff+K9zL4EgTVmKxLEmG7xOccSwzdPrM4LwULAAUCiIoBAAsACQM83OEAAAAAAAkCAAYMAgAAAAAbtwAAAAAAEQYABQAQCQwBAA4PCQwKAgABBQMNDwcQCAQSXgAA4DIpAAAAAAAAAAAAAAAAAMGhI2gAAAAADAkBCgALAQAIDAAABgAEAAIBAQ0ADgEAAxgAZgY9EgHa6+quClnNAQIAAGjN5REAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
|
||||||
"base64"
|
"base64"
|
||||||
],
|
],
|
||||||
"meta": {
|
"meta": {
|
||||||
@@ -8,187 +8,85 @@
|
|||||||
"status": {
|
"status": {
|
||||||
"Ok": null
|
"Ok": null
|
||||||
},
|
},
|
||||||
"fee": 115000,
|
"fee": 1500000,
|
||||||
"preBalances": [
|
"preBalances": [
|
||||||
1299959000,
|
2005440908,
|
||||||
0,
|
0,
|
||||||
20558783,
|
4696550893895,
|
||||||
|
13463471281,
|
||||||
|
377180764,
|
||||||
0,
|
0,
|
||||||
0,
|
57019670,
|
||||||
0,
|
4441807831495,
|
||||||
0,
|
2039280,
|
||||||
297249326667618,
|
|
||||||
1,
|
|
||||||
1,
|
1,
|
||||||
1141440,
|
1141440,
|
||||||
323296939,
|
1,
|
||||||
2500000,
|
|
||||||
1141440,
|
|
||||||
934087680,
|
934087680,
|
||||||
|
1141440,
|
||||||
|
1141440,
|
||||||
|
290898417,
|
||||||
|
1461600,
|
||||||
731913600,
|
731913600,
|
||||||
1009200,
|
137104014
|
||||||
0
|
|
||||||
],
|
],
|
||||||
"postBalances": [
|
"postBalances": [
|
||||||
162455200,
|
1686928628,
|
||||||
1461600,
|
0,
|
||||||
24558783,
|
4696553593895,
|
||||||
1101231920,
|
13760771281,
|
||||||
|
377329414,
|
||||||
2039280,
|
2039280,
|
||||||
15616720,
|
69019670,
|
||||||
|
4441810655845,
|
||||||
2039280,
|
2039280,
|
||||||
297249337667618,
|
|
||||||
1,
|
|
||||||
1,
|
1,
|
||||||
1141440,
|
1141440,
|
||||||
323296939,
|
1,
|
||||||
2500000,
|
|
||||||
1141440,
|
|
||||||
934087680,
|
934087680,
|
||||||
|
1141440,
|
||||||
|
1141440,
|
||||||
|
290898417,
|
||||||
|
1461600,
|
||||||
731913600,
|
731913600,
|
||||||
1009200,
|
137104014
|
||||||
0
|
|
||||||
],
|
],
|
||||||
"innerInstructions": [
|
"innerInstructions": [
|
||||||
{
|
{
|
||||||
"index": 3,
|
"index": 3,
|
||||||
"instructions": [
|
"instructions": [
|
||||||
{
|
{
|
||||||
"programIdIndex": 9,
|
"programIdIndex": 12,
|
||||||
"accounts": [
|
"accounts": [
|
||||||
0,
|
16
|
||||||
1
|
|
||||||
],
|
|
||||||
"data": "11114XtYk9gGfZoo968fyjNUYQJKf9gdmkGoaoBpzFv4vyaSMBn3VKxZdv7mZLzoyX5YNC",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 14,
|
|
||||||
"accounts": [
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"data": "2zt6UCCHp66bJGRS4G7bTsjdxFh6FQ9sBEyRfGyPQKxYisAw",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 9,
|
|
||||||
"accounts": [
|
|
||||||
0,
|
|
||||||
3
|
|
||||||
],
|
|
||||||
"data": "11112npZeiggj74jpdjnyaoXKQznZSuR59vRrSV7vxdg9g2eRJ4seDwRwaQLDUqBNSEnrB",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 15,
|
|
||||||
"accounts": [
|
|
||||||
0,
|
|
||||||
4,
|
|
||||||
3,
|
|
||||||
1,
|
|
||||||
9,
|
|
||||||
14
|
|
||||||
],
|
|
||||||
"data": "1",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 14,
|
|
||||||
"accounts": [
|
|
||||||
1
|
|
||||||
],
|
],
|
||||||
"data": "84eT",
|
"data": "84eT",
|
||||||
"stackHeight": 3
|
"stackHeight": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"programIdIndex": 9,
|
"programIdIndex": 9,
|
||||||
"accounts": [
|
"accounts": [
|
||||||
0,
|
0,
|
||||||
4
|
5
|
||||||
],
|
],
|
||||||
"data": "11119os1e9qSs2u7TsThXqkBSRVFxhmYaFKFZ1waB2X7armDmvK3p5GmLdUxYdg3h7QSrL",
|
"data": "11119os1e9qSs2u7TsThXqkBSRVFxhmYaFKFZ1waB2X7armDmvK3p5GmLdUxYdg3h7QSrL",
|
||||||
"stackHeight": 3
|
"stackHeight": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"programIdIndex": 14,
|
"programIdIndex": 12,
|
||||||
"accounts": [
|
"accounts": [
|
||||||
4
|
5
|
||||||
],
|
],
|
||||||
"data": "P",
|
"data": "P",
|
||||||
"stackHeight": 3
|
"stackHeight": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"programIdIndex": 14,
|
"programIdIndex": 12,
|
||||||
"accounts": [
|
|
||||||
4,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"data": "6R9wJMnJhbG9ZQYKJuVP2PB6vT2C61iaQx6VwGbPagDmk",
|
|
||||||
"stackHeight": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 13,
|
|
||||||
"accounts": [
|
"accounts": [
|
||||||
5,
|
5,
|
||||||
1,
|
16
|
||||||
11,
|
|
||||||
0,
|
|
||||||
11,
|
|
||||||
9
|
|
||||||
],
|
],
|
||||||
"data": "sCA7VhscVFkCjwGP776CKweeQ17GA3y6hoefZyQZ7igmWRvSXA49qEc3vT7wBUxVA13HoHqvXDFZ4UuibYrj1fSiqN7Hw2T1PxZfuF1ebruak4VwaCoseJMTaoCSRGbUZZSf",
|
"data": "6UhFp3r3cKbQWwHQYPuDqtb5CAdjXP45vy8Z8DQwgGRSQ",
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 9,
|
|
||||||
"accounts": [
|
|
||||||
0,
|
|
||||||
5
|
|
||||||
],
|
|
||||||
"data": "3Bxs4bhMrSrmPkVD",
|
|
||||||
"stackHeight": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 9,
|
|
||||||
"accounts": [
|
|
||||||
5
|
|
||||||
],
|
|
||||||
"data": "9krTDUMpjBo4wxLP",
|
|
||||||
"stackHeight": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 9,
|
|
||||||
"accounts": [
|
|
||||||
5
|
|
||||||
],
|
|
||||||
"data": "SYXsBkG6yKW2wWDcW8EDHR6D3P82bKxJGPpM65DD8nHqBfMP",
|
|
||||||
"stackHeight": 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 14,
|
|
||||||
"accounts": [
|
|
||||||
1,
|
|
||||||
4,
|
|
||||||
11
|
|
||||||
],
|
|
||||||
"data": "6ApXSNCamGdm",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 14,
|
|
||||||
"accounts": [
|
|
||||||
1,
|
|
||||||
11
|
|
||||||
],
|
|
||||||
"data": "31tb",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 10,
|
|
||||||
"accounts": [
|
|
||||||
17
|
|
||||||
],
|
|
||||||
"data": "7iazyA59wwtAStxsqtCeosLjmdhF7YPNeRh62abjnRpjo8BFJQyM79SCTR8EdrQNP4pFWzB9LRwFM7eYmn6zhAZ8UjEWrgARNaSmjuLGwaXuB6CQiRHZ2XpENVyDtB5adZ2hqDvmbGzTNsMd9CvgKxusSLTGhhW5Y7b4jvGji585fx1Bq3XKBg6Zr1mCNjcVFzQ45dRSbDad9ZQaVjDLSHMRVuwNvhvLM3RQCJLhyo4e6S156JeFmweeAp7HqHvGw3fVitNxwbrmnU8MsJ9",
|
|
||||||
"stackHeight": 2
|
"stackHeight": 2
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -196,54 +94,52 @@
|
|||||||
{
|
{
|
||||||
"index": 4,
|
"index": 4,
|
||||||
"instructions": [
|
"instructions": [
|
||||||
{
|
|
||||||
"programIdIndex": 14,
|
|
||||||
"accounts": [
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"data": "84eT",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"programIdIndex": 9,
|
"programIdIndex": 9,
|
||||||
"accounts": [
|
"accounts": [
|
||||||
0,
|
0,
|
||||||
6
|
2
|
||||||
],
|
],
|
||||||
"data": "11119os1e9qSs2u7TsThXqkBSRVFxhmYaFKFZ1waB2X7armDmvK3p5GmLdUxYdg3h7QSrL",
|
"data": "3Bxs4eMeB358Cb5h",
|
||||||
"stackHeight": 2
|
"stackHeight": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"programIdIndex": 14,
|
"programIdIndex": 10,
|
||||||
"accounts": [
|
|
||||||
6
|
|
||||||
],
|
|
||||||
"data": "P",
|
|
||||||
"stackHeight": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"programIdIndex": 14,
|
|
||||||
"accounts": [
|
|
||||||
6,
|
|
||||||
1
|
|
||||||
],
|
|
||||||
"data": "6dhk2iczksvz6s1rFHcSMywmmwmB1z7XmGVUbnAVDoyj7",
|
|
||||||
"stackHeight": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 5,
|
|
||||||
"instructions": [
|
|
||||||
{
|
|
||||||
"programIdIndex": 14,
|
|
||||||
"accounts": [
|
"accounts": [
|
||||||
|
15,
|
||||||
|
7,
|
||||||
|
16,
|
||||||
|
3,
|
||||||
|
8,
|
||||||
|
5,
|
||||||
|
0,
|
||||||
|
9,
|
||||||
|
12,
|
||||||
4,
|
4,
|
||||||
6,
|
18,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"data": "AJTQ2h9DXrBo1MiibpgfkQHmpSKmNnQgP",
|
||||||
|
"stackHeight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"programIdIndex": 12,
|
||||||
|
"accounts": [
|
||||||
|
8,
|
||||||
|
5,
|
||||||
3
|
3
|
||||||
],
|
],
|
||||||
"data": "3LUFBVrqeiX9",
|
"data": "3SpdELLWnXkK",
|
||||||
"stackHeight": 2
|
"stackHeight": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"programIdIndex": 9,
|
||||||
|
"accounts": [
|
||||||
|
0,
|
||||||
|
4
|
||||||
|
],
|
||||||
|
"data": "3Bxs4VLT5WjmR4oh",
|
||||||
|
"stackHeight": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"programIdIndex": 9,
|
"programIdIndex": 9,
|
||||||
@@ -251,8 +147,8 @@
|
|||||||
0,
|
0,
|
||||||
3
|
3
|
||||||
],
|
],
|
||||||
"data": "3Bxs3zyALUmzCtNB",
|
"data": "3Bxs46HNXQ8jq79R",
|
||||||
"stackHeight": 2
|
"stackHeight": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"programIdIndex": 9,
|
"programIdIndex": 9,
|
||||||
@@ -260,16 +156,16 @@
|
|||||||
0,
|
0,
|
||||||
7
|
7
|
||||||
],
|
],
|
||||||
"data": "3Bxs4Z7Wb6tTKEWB",
|
"data": "3Bxs4TJNecvxKcVV",
|
||||||
"stackHeight": 2
|
"stackHeight": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"programIdIndex": 10,
|
"programIdIndex": 10,
|
||||||
"accounts": [
|
"accounts": [
|
||||||
17
|
18
|
||||||
],
|
],
|
||||||
"data": "2K7nL28PxCW8ejnyCeuMpbXaZKMjMgWS9mpWYzdhxxxazMRueEhr8dhzoSv8cJB4QmssgbcPVf7uHyA7xpBWFRc9qBGRzEzUtR1t2P8uGyxRepqEGGoak55qnosFUyXaDoRPdY3r2GR952e4KnxiYyGBD4epcJmcs5akyXSEueVSCuYxtXDaCp7HgAoy",
|
"data": "2zjR1PvPvgqdhPdZLxuWCL7GiE5h1bKn4ziAcRd2FBFaC3kf2EYsG31a2aigsk9mgAfieqmo561JLMNk2uSKF65QKzv64GtLAULg9zNrDFfLe7DrBDcgQBwTwRqqLVkWBrksYNBFeyBeSPwcQe5DNEEqwfSowV6pk2t9QuN6JDSpxRegP8ekTV5zwc3ytD2hSo7wu9s4ynRb5ccHwRaoy9Lzm7M66sikRLa74mXuFzdjzGuq454PDDP8eqUSWxt1ddTchsUvqsAnv92vMN2BLu7XZ3UcTv96fz8KrV93qqHSsNwfKdCsY7QMwxbCE7R",
|
||||||
"stackHeight": 2
|
"stackHeight": 3
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -277,72 +173,15 @@
|
|||||||
"logMessages": [
|
"logMessages": [
|
||||||
"Program ComputeBudget111111111111111111111111111111 invoke [1]",
|
"Program ComputeBudget111111111111111111111111111111 invoke [1]",
|
||||||
"Program ComputeBudget111111111111111111111111111111 success",
|
"Program ComputeBudget111111111111111111111111111111 success",
|
||||||
"Program 11111111111111111111111111111111 invoke [1]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
|
||||||
"Program ComputeBudget111111111111111111111111111111 invoke [1]",
|
"Program ComputeBudget111111111111111111111111111111 invoke [1]",
|
||||||
"Program ComputeBudget111111111111111111111111111111 success",
|
"Program ComputeBudget111111111111111111111111111111 success",
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]",
|
"Program 11111111111111111111111111111111 invoke [1]",
|
||||||
"Program log: Instruction: Create",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [2]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
"Program 11111111111111111111111111111111 success",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
|
||||||
"Program log: Instruction: InitializeMint2",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2780 of 238190 compute units",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [2]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
|
||||||
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [2]",
|
|
||||||
"Program log: Create",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]",
|
|
||||||
"Program log: Instruction: GetAccountDataSize",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1595 of 212794 compute units",
|
|
||||||
"Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [3]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
|
||||||
"Program log: Initialize the associated token account",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]",
|
|
||||||
"Program log: Instruction: InitializeImmutableOwner",
|
|
||||||
"Program log: Please upgrade to SPL Token 2022 for immutable owner support",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 206181 compute units",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]",
|
|
||||||
"Program log: Instruction: InitializeAccount3",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4214 of 202297 compute units",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
|
||||||
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 21990 of 219769 compute units",
|
|
||||||
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
|
|
||||||
"Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s invoke [2]",
|
|
||||||
"Program log: IX: Create Metadata Accounts v3",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [3]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
|
||||||
"Program log: Allocate space for the account",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [3]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
|
||||||
"Program log: Assign the account to the owning program",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [3]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
|
||||||
"Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s consumed 37631 of 181110 compute units",
|
|
||||||
"Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s success",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
|
||||||
"Program log: Instruction: MintTo",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4492 of 140964 compute units",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
|
||||||
"Program log: Instruction: SetAuthority",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 2911 of 134325 compute units",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]",
|
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2003 of 127301 compute units",
|
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
|
|
||||||
"Program data: G3KpTd7rY3YDAAAAZG9kAwAAAERPREcAAABodHRwczovL2NmLWlwZnMuY29tL2lwZnMvUW1ZMW0yb3doakJaenkxTXRoWW1XaW4zWHdHaW1HS1dDNVp3TlhQQ2JiYUIxa75Oab9+zoJi5E/7feiMCGSkHpgBjBAk2HT/Omepbi/vO7+83IaPqzQCmuexYmfBKhW99pBf1HY/TQqasw1nKrv2MdL3xlA70bgIpTlRVYJ5yU7c4gCGkVyzuRpXUJYvmg==",
|
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 126103 of 249550 compute units",
|
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
|
|
||||||
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
|
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]",
|
||||||
"Program log: Create",
|
"Program log: Create",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
||||||
"Program log: Instruction: GetAccountDataSize",
|
"Program log: Instruction: GetAccountDataSize",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1569 of 118084 compute units",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1569 of 93653 compute units",
|
||||||
"Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=",
|
"Program return: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA pQAAAAAAAAA=",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
||||||
"Program 11111111111111111111111111111111 invoke [2]",
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
@@ -351,55 +190,76 @@
|
|||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
||||||
"Program log: Instruction: InitializeImmutableOwner",
|
"Program log: Instruction: InitializeImmutableOwner",
|
||||||
"Program log: Please upgrade to SPL Token 2022 for immutable owner support",
|
"Program log: Please upgrade to SPL Token 2022 for immutable owner support",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 111497 compute units",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 1405 of 87066 compute units",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
||||||
"Program log: Instruction: InitializeAccount3",
|
"Program log: Instruction: InitializeAccount3",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4188 of 107617 compute units",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4188 of 83184 compute units",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
||||||
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 20301 of 123447 compute units",
|
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 21837 of 100550 compute units",
|
||||||
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
|
"Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success",
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [1]",
|
"Program b1oomGGqPKGD6errbyfbVMBuzSC8WtAAYo8MwNafWW1 invoke [1]",
|
||||||
"Program log: Instruction: Buy",
|
"Program log: Powered by https://telegram.bloombot.app",
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [2]",
|
|
||||||
"Program log: Instruction: Transfer",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 81505 compute units",
|
|
||||||
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [2]",
|
|
||||||
"Program 11111111111111111111111111111111 success",
|
|
||||||
"Program 11111111111111111111111111111111 invoke [2]",
|
"Program 11111111111111111111111111111111 invoke [2]",
|
||||||
"Program 11111111111111111111111111111111 success",
|
"Program 11111111111111111111111111111111 success",
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]",
|
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [2]",
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2003 of 69417 compute units",
|
"Program log: Instruction: Buy",
|
||||||
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [3]",
|
||||||
|
"Program log: Instruction: Transfer",
|
||||||
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA consumed 4645 of 49415 compute units",
|
||||||
|
"Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [3]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [3]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program 11111111111111111111111111111111 invoke [3]",
|
||||||
|
"Program 11111111111111111111111111111111 success",
|
||||||
|
"Program data: vdt/007mYe5E+dQlVubfmlZx8g4Yr7VZS6dIqY5CCXXxzYTAYMWwbyBwuBEAAAAAT+SenZMEAAABcFi8Lm3PgW7X4XZm7q8+G4Jf4IaSLzptQdkNfSFrd2m6oSNoAAAAALHaOjAKAAAAgP3BigudAgCxLhc0AwAAAIBlrz56ngEA16qPsGDYKRtMTUddr/diyWvcDazrNsAS6tEu06lIQWFfAAAAAAAAAJ4YKwAAAAAAkJajVbvLxqgCZ/z53+NIXoh5GMXQLRXjoGjmO6GR/6UFAAAAAAAAAKpEAgAAAAAA",
|
||||||
|
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P invoke [3]",
|
||||||
|
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 2006 of 33261 compute units",
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
|
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
|
||||||
"Program data: vdt/007mYe6+Tmm/fs6CYuRP+33ojAhkpB6YAYwQJNh0/zpnqW4v7wCrkEEAAAAAKeutVYQiAAAB9jHS98ZQO9G4CKU5UVWCeclO3OIAhpFcs7kaV1CWL5oKQsNmAAAAAABXtD0HAAAA1yQq8l6tAwAAq5BBAAAAANeMF6bNrgIA",
|
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 40072 of 70491 compute units",
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P consumed 37457 of 103146 compute units",
|
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success",
|
||||||
"Program 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P success"
|
"Program b1oomGGqPKGD6errbyfbVMBuzSC8WtAAYo8MwNafWW1 consumed 48895 of 78713 compute units",
|
||||||
|
"Program b1oomGGqPKGD6errbyfbVMBuzSC8WtAAYo8MwNafWW1 success"
|
||||||
|
],
|
||||||
|
"preTokenBalances": [
|
||||||
|
{
|
||||||
|
"accountIndex": 8,
|
||||||
|
"mint": "5eFg3giaX2c3RydHvx1S3yEKpYjBuwtLUsmbAAG9pump",
|
||||||
|
"uiTokenAmount": {
|
||||||
|
"uiAmount": 667654902.731215,
|
||||||
|
"decimals": 6,
|
||||||
|
"amount": "667654902731215",
|
||||||
|
"uiAmountString": "667654902.731215"
|
||||||
|
},
|
||||||
|
"owner": "7Q1e26aB8kpyamjKPCt5oD73b2Hx7nAEjAMUwfHmZy7G",
|
||||||
|
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"preTokenBalances": [],
|
|
||||||
"postTokenBalances": [
|
"postTokenBalances": [
|
||||||
{
|
{
|
||||||
"accountIndex": 4,
|
"accountIndex": 5,
|
||||||
"mint": "Dosp4t6w5kDzAgBQBMEsZSUNzdwTC5zHYiVZQqMKpump",
|
"mint": "5eFg3giaX2c3RydHvx1S3yEKpYjBuwtLUsmbAAG9pump",
|
||||||
"uiTokenAmount": {
|
"uiTokenAmount": {
|
||||||
"uiAmount": 962048231.511255,
|
"uiAmount": 5032051.139663,
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"amount": "962048231511255",
|
"amount": "5032051139663",
|
||||||
"uiAmountString": "962048231.511255"
|
"uiAmountString": "5032051.139663"
|
||||||
},
|
},
|
||||||
"owner": "52EdRamuJQsj94DnpLBguCfXx8cGbyJiFBL5n1hmP5Ln",
|
"owner": "8ZZ97eWp2k8gfoK2Jk2WQcdofk9hyJpEGDPGiqFryH1S",
|
||||||
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"accountIndex": 6,
|
"accountIndex": 8,
|
||||||
"mint": "Dosp4t6w5kDzAgBQBMEsZSUNzdwTC5zHYiVZQqMKpump",
|
"mint": "5eFg3giaX2c3RydHvx1S3yEKpYjBuwtLUsmbAAG9pump",
|
||||||
"uiTokenAmount": {
|
"uiTokenAmount": {
|
||||||
"uiAmount": 37951768.488745,
|
"uiAmount": 662622851.591552,
|
||||||
"decimals": 6,
|
"decimals": 6,
|
||||||
"amount": "37951768488745",
|
"amount": "662622851591552",
|
||||||
"uiAmountString": "37951768.488745"
|
"uiAmountString": "662622851.591552"
|
||||||
},
|
},
|
||||||
"owner": "Ha3MnRTxb5iGbXkjCTF2VyLPSsbCaNG4ZaJkHaoQWqJ9",
|
"owner": "7Q1e26aB8kpyamjKPCt5oD73b2Hx7nAEjAMUwfHmZy7G",
|
||||||
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -408,7 +268,7 @@
|
|||||||
"writable": [],
|
"writable": [],
|
||||||
"readonly": []
|
"readonly": []
|
||||||
},
|
},
|
||||||
"computeUnitsConsumed": 184311
|
"computeUnitsConsumed": 71182
|
||||||
},
|
},
|
||||||
"version": 0
|
"version": "legacy"
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,11 @@ import asyncio
|
|||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
|
|
||||||
import websockets
|
import websockets
|
||||||
|
from solders.pubkey import Pubkey
|
||||||
|
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
PUMP_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
|
||||||
|
|
||||||
from core.pubkeys import PumpAddresses
|
|
||||||
|
|
||||||
WSS_ENDPOINT = os.environ.get("SOLANA_NODE_WSS_ENDPOINT")
|
WSS_ENDPOINT = os.environ.get("SOLANA_NODE_WSS_ENDPOINT")
|
||||||
|
|
||||||
|
|
||||||
@@ -30,7 +27,7 @@ async def listen_for_transactions():
|
|||||||
"id": 1,
|
"id": 1,
|
||||||
"method": "blockSubscribe",
|
"method": "blockSubscribe",
|
||||||
"params": [
|
"params": [
|
||||||
{"mentionsAccountOrProgram": str(PumpAddresses.PROGRAM)},
|
{"mentionsAccountOrProgram": str(PUMP_PROGRAM)},
|
||||||
{
|
{
|
||||||
"commitment": "confirmed",
|
"commitment": "confirmed",
|
||||||
"encoding": "base64",
|
"encoding": "base64",
|
||||||
@@ -42,7 +39,7 @@ async def listen_for_transactions():
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
await websocket.send(subscription_message)
|
await websocket.send(subscription_message)
|
||||||
print(f"Subscribed to blocks mentioning program: {PumpAddresses.PROGRAM}")
|
print(f"Subscribed to blocks mentioning program: {PUMP_PROGRAM}")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
"""
|
"""
|
||||||
Module for checking the status of a token's bonding curve on the Solana network using
|
Module for checking the status of a token's bonding curve on the Solana network using
|
||||||
the Pump.fun program. It allows querying the bonding curve state and completion status.
|
the Pump.fun program. It allows querying the bonding curve state and completion status.
|
||||||
|
|
||||||
|
Note: creator fee upgrade introduced updates in bonding curve structure.
|
||||||
|
https://github.com/pump-fun/pump-public-docs/blob/main/docs/PUMP_CREATOR_FEE_README.md
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -8,7 +11,7 @@ import os
|
|||||||
import struct
|
import struct
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
from construct import Flag, Int64ul, Struct
|
from construct import Bytes, Flag, Int64ul, Struct
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from solana.rpc.async_api import AsyncClient
|
from solana.rpc.async_api import AsyncClient
|
||||||
from solders.pubkey import Pubkey
|
from solders.pubkey import Pubkey
|
||||||
@@ -37,7 +40,7 @@ class BondingCurveState:
|
|||||||
token_total_supply: Total token supply in the curve
|
token_total_supply: Total token supply in the curve
|
||||||
complete: Whether the curve has completed and liquidity migrated
|
complete: Whether the curve has completed and liquidity migrated
|
||||||
"""
|
"""
|
||||||
_STRUCT = Struct(
|
_STRUCT_1 = Struct(
|
||||||
"virtual_token_reserves" / Int64ul,
|
"virtual_token_reserves" / Int64ul,
|
||||||
"virtual_sol_reserves" / Int64ul,
|
"virtual_sol_reserves" / Int64ul,
|
||||||
"real_token_reserves" / Int64ul,
|
"real_token_reserves" / Int64ul,
|
||||||
@@ -46,9 +49,33 @@ class BondingCurveState:
|
|||||||
"complete" / Flag,
|
"complete" / Flag,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Struct after creator fee update has been introduced
|
||||||
|
# https://github.com/pump-fun/pump-public-docs/blob/main/docs/PUMP_CREATOR_FEE_README.md
|
||||||
|
_STRUCT_2 = Struct(
|
||||||
|
"virtual_token_reserves" / Int64ul,
|
||||||
|
"virtual_sol_reserves" / Int64ul,
|
||||||
|
"real_token_reserves" / Int64ul,
|
||||||
|
"real_sol_reserves" / Int64ul,
|
||||||
|
"token_total_supply" / Int64ul,
|
||||||
|
"complete" / Flag,
|
||||||
|
"creator" / Bytes(32), # Added new creator field - 32 bytes for Pubkey
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, data: bytes) -> None:
|
def __init__(self, data: bytes) -> None:
|
||||||
parsed = self._STRUCT.parse(data[8:])
|
"""Parse bonding curve data."""
|
||||||
self.__dict__.update(parsed)
|
if data[:8] != EXPECTED_DISCRIMINATOR:
|
||||||
|
raise ValueError("Invalid curve state discriminator")
|
||||||
|
|
||||||
|
if len(data) < 150:
|
||||||
|
parsed = self._STRUCT_1.parse(data[8:])
|
||||||
|
self.__dict__.update(parsed)
|
||||||
|
|
||||||
|
else:
|
||||||
|
parsed = self._STRUCT_1.parse(data[8:])
|
||||||
|
self.__dict__.update(parsed)
|
||||||
|
# Convert raw bytes to Pubkey for creator field
|
||||||
|
if hasattr(self, 'creator') and isinstance(self.creator, bytes):
|
||||||
|
self.creator = Pubkey.from_bytes(self.creator)
|
||||||
|
|
||||||
|
|
||||||
def get_associated_bonding_curve_address(
|
def get_associated_bonding_curve_address(
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from solders.pubkey import Pubkey
|
from solders.pubkey import Pubkey
|
||||||
|
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
# Global constants
|
||||||
|
PUMP_PROGRAM = Pubkey.from_string("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P")
|
||||||
from core.pubkeys import PumpAddresses, SystemAddresses
|
SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
|
||||||
|
SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string(
|
||||||
|
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
|
||||||
|
)
|
||||||
|
|
||||||
def get_bonding_curve_address(mint: Pubkey, program_id: Pubkey) -> tuple[Pubkey, int]:
|
def get_bonding_curve_address(mint: Pubkey, program_id: Pubkey) -> tuple[Pubkey, int]:
|
||||||
"""
|
"""
|
||||||
@@ -24,10 +23,10 @@ def find_associated_bonding_curve(mint: Pubkey, bonding_curve: Pubkey) -> Pubkey
|
|||||||
derived_address, _ = Pubkey.find_program_address(
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
[
|
[
|
||||||
bytes(bonding_curve),
|
bytes(bonding_curve),
|
||||||
bytes(SystemAddresses.TOKEN_PROGRAM),
|
bytes(SYSTEM_TOKEN_PROGRAM),
|
||||||
bytes(mint),
|
bytes(mint),
|
||||||
],
|
],
|
||||||
SystemAddresses.ASSOCIATED_TOKEN_PROGRAM,
|
SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM,
|
||||||
)
|
)
|
||||||
return derived_address
|
return derived_address
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ def main():
|
|||||||
mint = Pubkey.from_string(mint_address)
|
mint = Pubkey.from_string(mint_address)
|
||||||
|
|
||||||
bonding_curve_address, bump = get_bonding_curve_address(
|
bonding_curve_address, bump = get_bonding_curve_address(
|
||||||
mint, PumpAddresses.PROGRAM
|
mint, PUMP_PROGRAM
|
||||||
)
|
)
|
||||||
|
|
||||||
# Calculate the associated bonding curve
|
# Calculate the associated bonding curve
|
||||||
@@ -56,7 +55,7 @@ def main():
|
|||||||
print("-" * 50)
|
print("-" * 50)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(f"Error: Invalid address format - {str(e)}")
|
print(f"Error: Invalid address format - {e!s}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ def decode_instruction(ix_data, ix_def):
|
|||||||
if arg["type"] == "u64":
|
if arg["type"] == "u64":
|
||||||
value = struct.unpack_from("<Q", ix_data, offset)[0]
|
value = struct.unpack_from("<Q", ix_data, offset)[0]
|
||||||
offset += 8
|
offset += 8
|
||||||
elif arg["type"] == "publicKey":
|
elif arg["type"] == "pubkey":
|
||||||
value = ix_data[offset : offset + 32].hex()
|
value = ix_data[offset : offset + 32].hex()
|
||||||
offset += 32
|
offset += 32
|
||||||
elif arg["type"] == "string":
|
elif arg["type"] == "string":
|
||||||
@@ -76,9 +76,8 @@ def decode_transaction(tx_data, idl):
|
|||||||
program_id = str(account_keys[ix.program_id_index])
|
program_id = str(account_keys[ix.program_id_index])
|
||||||
print(f"\nInstruction {idx}:")
|
print(f"\nInstruction {idx}:")
|
||||||
print(f"Program ID: {program_id}")
|
print(f"Program ID: {program_id}")
|
||||||
print(f"IDL program address: {idl['metadata']['address']}")
|
|
||||||
|
|
||||||
if program_id == idl["metadata"]["address"]:
|
if program_id == "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P": # Pump Fun Program
|
||||||
ix_data = bytes(ix.data)
|
ix_data = bytes(ix.data)
|
||||||
discriminator = struct.unpack("<Q", ix_data[:8])[0]
|
discriminator = struct.unpack("<Q", ix_data[:8])[0]
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import base64
|
|||||||
import json
|
import json
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from construct import Flag, Int64ul, Struct
|
from construct import Bytes, Flag, Int64ul, Struct
|
||||||
|
from solders.pubkey import Pubkey
|
||||||
|
|
||||||
LAMPORTS_PER_SOL = 1_000_000_000
|
LAMPORTS_PER_SOL = 1_000_000_000
|
||||||
TOKEN_DECIMALS = 6
|
TOKEN_DECIMALS = 6
|
||||||
@@ -10,7 +11,7 @@ EXPECTED_DISCRIMINATOR = struct.pack("<Q", 6966180631402821399)
|
|||||||
|
|
||||||
|
|
||||||
class BondingCurveState:
|
class BondingCurveState:
|
||||||
_STRUCT = Struct(
|
_STRUCT_1 = Struct(
|
||||||
"virtual_token_reserves" / Int64ul,
|
"virtual_token_reserves" / Int64ul,
|
||||||
"virtual_sol_reserves" / Int64ul,
|
"virtual_sol_reserves" / Int64ul,
|
||||||
"real_token_reserves" / Int64ul,
|
"real_token_reserves" / Int64ul,
|
||||||
@@ -19,9 +20,33 @@ class BondingCurveState:
|
|||||||
"complete" / Flag,
|
"complete" / Flag,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Struct after creator fee update has been introduced
|
||||||
|
# https://github.com/pump-fun/pump-public-docs/blob/main/docs/PUMP_CREATOR_FEE_README.md
|
||||||
|
_STRUCT_2 = Struct(
|
||||||
|
"virtual_token_reserves" / Int64ul,
|
||||||
|
"virtual_sol_reserves" / Int64ul,
|
||||||
|
"real_token_reserves" / Int64ul,
|
||||||
|
"real_sol_reserves" / Int64ul,
|
||||||
|
"token_total_supply" / Int64ul,
|
||||||
|
"complete" / Flag,
|
||||||
|
"creator" / Bytes(32), # Added new creator field - 32 bytes for Pubkey
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, data: bytes) -> None:
|
def __init__(self, data: bytes) -> None:
|
||||||
parsed = self._STRUCT.parse(data[8:])
|
"""Parse bonding curve data."""
|
||||||
self.__dict__.update(parsed)
|
if data[:8] != EXPECTED_DISCRIMINATOR:
|
||||||
|
raise ValueError("Invalid curve state discriminator")
|
||||||
|
|
||||||
|
if len(data) < 150:
|
||||||
|
parsed = self._STRUCT_1.parse(data[8:])
|
||||||
|
self.__dict__.update(parsed)
|
||||||
|
|
||||||
|
else:
|
||||||
|
parsed = self._STRUCT_2.parse(data[8:])
|
||||||
|
self.__dict__.update(parsed)
|
||||||
|
# Convert raw bytes to Pubkey for creator field
|
||||||
|
if hasattr(self, 'creator') and isinstance(self.creator, bytes):
|
||||||
|
self.creator = Pubkey.from_bytes(self.creator)
|
||||||
|
|
||||||
|
|
||||||
def calculate_bonding_curve_price(curve_state: BondingCurveState) -> float:
|
def calculate_bonding_curve_price(curve_state: BondingCurveState) -> float:
|
||||||
@@ -41,7 +66,7 @@ def decode_bonding_curve_data(raw_data: str) -> BondingCurveState:
|
|||||||
|
|
||||||
|
|
||||||
# Load the JSON data
|
# Load the JSON data
|
||||||
with open("learning-examples/raw_bondingCurve_from_getAccountInfo.json", "r") as file:
|
with open("learning-examples/raw_bondingCurve_from_getAccountInfo.json") as file:
|
||||||
json_data = json.load(file)
|
json_data = json.load(file)
|
||||||
|
|
||||||
# Extract the base64 encoded data
|
# Extract the base64 encoded data
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ for ix in instructions:
|
|||||||
if "parsed" in ix:
|
if "parsed" in ix:
|
||||||
print(f"Parsed instruction: {ix['program']} - {ix['parsed']['type']}")
|
print(f"Parsed instruction: {ix['program']} - {ix['parsed']['type']}")
|
||||||
print(f"Info: {json.dumps(ix['parsed']['info'], indent=2)}")
|
print(f"Info: {json.dumps(ix['parsed']['info'], indent=2)}")
|
||||||
elif program_id == idl["metadata"]["address"]:
|
elif program_id == "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P": # Pump Fun Program
|
||||||
matching_instruction = find_matching_instruction(accounts, data)
|
matching_instruction = find_matching_instruction(accounts, data)
|
||||||
if matching_instruction:
|
if matching_instruction:
|
||||||
decoded_data = decode_instruction_data(
|
decoded_data = decode_instruction_data(
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ def parse_market_account_data(data):
|
|||||||
("pool_base_token_account", "pubkey"),
|
("pool_base_token_account", "pubkey"),
|
||||||
("pool_quote_token_account", "pubkey"),
|
("pool_quote_token_account", "pubkey"),
|
||||||
("lp_supply", "u64"),
|
("lp_supply", "u64"),
|
||||||
|
("coin_creator", "pubkey")
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import struct
|
|||||||
import base58
|
import base58
|
||||||
import spl.token.instructions as spl_token
|
import spl.token.instructions as spl_token
|
||||||
import websockets
|
import websockets
|
||||||
from construct import Flag, Int64ul, Struct
|
from construct import Bytes, Flag, Int64ul, Struct
|
||||||
from solana.rpc.async_api import AsyncClient
|
from solana.rpc.async_api import AsyncClient
|
||||||
from solana.rpc.commitment import Confirmed
|
from solana.rpc.commitment import Confirmed
|
||||||
from solana.rpc.types import TxOpts
|
from solana.rpc.types import TxOpts
|
||||||
@@ -36,7 +36,6 @@ SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss62
|
|||||||
SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string(
|
SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string(
|
||||||
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
|
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
|
||||||
)
|
)
|
||||||
SYSTEM_RENT = Pubkey.from_string("SysvarRent111111111111111111111111111111111")
|
|
||||||
SOL = Pubkey.from_string("So11111111111111111111111111111111111111112")
|
SOL = Pubkey.from_string("So11111111111111111111111111111111111111112")
|
||||||
LAMPORTS_PER_SOL = 1_000_000_000
|
LAMPORTS_PER_SOL = 1_000_000_000
|
||||||
|
|
||||||
@@ -53,12 +52,21 @@ class BondingCurveState:
|
|||||||
"real_sol_reserves" / Int64ul,
|
"real_sol_reserves" / Int64ul,
|
||||||
"token_total_supply" / Int64ul,
|
"token_total_supply" / Int64ul,
|
||||||
"complete" / Flag,
|
"complete" / Flag,
|
||||||
|
"creator" / Bytes(32), # Added new creator field - 32 bytes for Pubkey
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, data: bytes) -> None:
|
def __init__(self, data: bytes) -> None:
|
||||||
|
"""Parse bonding curve data."""
|
||||||
|
if data[:8] != EXPECTED_DISCRIMINATOR:
|
||||||
|
raise ValueError("Invalid curve state discriminator")
|
||||||
|
|
||||||
parsed = self._STRUCT.parse(data[8:])
|
parsed = self._STRUCT.parse(data[8:])
|
||||||
self.__dict__.update(parsed)
|
self.__dict__.update(parsed)
|
||||||
|
|
||||||
|
# Convert raw bytes to Pubkey for creator field
|
||||||
|
if hasattr(self, 'creator') and isinstance(self.creator, bytes):
|
||||||
|
self.creator = Pubkey.from_bytes(self.creator)
|
||||||
|
|
||||||
|
|
||||||
async def get_pump_curve_state(
|
async def get_pump_curve_state(
|
||||||
conn: AsyncClient, curve_address: Pubkey
|
conn: AsyncClient, curve_address: Pubkey
|
||||||
@@ -83,10 +91,22 @@ def calculate_pump_curve_price(curve_state: BondingCurveState) -> float:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _find_creator_vault(creator: Pubkey) -> Pubkey:
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"creator-vault",
|
||||||
|
bytes(creator)
|
||||||
|
],
|
||||||
|
PUMP_PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
async def buy_token(
|
async def buy_token(
|
||||||
mint: Pubkey,
|
mint: Pubkey,
|
||||||
bonding_curve: Pubkey,
|
bonding_curve: Pubkey,
|
||||||
associated_bonding_curve: Pubkey,
|
associated_bonding_curve: Pubkey,
|
||||||
|
creator_vault: Pubkey,
|
||||||
amount: float,
|
amount: float,
|
||||||
slippage: float = 0.25,
|
slippage: float = 0.25,
|
||||||
max_retries=5,
|
max_retries=5,
|
||||||
@@ -188,7 +208,7 @@ async def buy_token(
|
|||||||
AccountMeta(
|
AccountMeta(
|
||||||
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
|
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
|
||||||
),
|
),
|
||||||
AccountMeta(pubkey=SYSTEM_RENT, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=creator_vault, is_signer=False, is_writable=True),
|
||||||
AccountMeta(
|
AccountMeta(
|
||||||
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
|
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
|
||||||
),
|
),
|
||||||
@@ -254,8 +274,8 @@ def decode_create_instruction(ix_data, ix_def, accounts):
|
|||||||
offset += 4
|
offset += 4
|
||||||
value = ix_data[offset : offset + length].decode("utf-8")
|
value = ix_data[offset : offset + length].decode("utf-8")
|
||||||
offset += length
|
offset += length
|
||||||
elif arg["type"] == "publicKey":
|
elif arg["type"] == "pubkey":
|
||||||
value = base64.b64encode(ix_data[offset : offset + 32]).decode("utf-8")
|
value = base58.b58encode(ix_data[offset : offset + 32]).decode("utf-8")
|
||||||
offset += 32
|
offset += 32
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported type: {arg['type']}")
|
raise ValueError(f"Unsupported type: {arg['type']}")
|
||||||
@@ -362,6 +382,7 @@ async def main():
|
|||||||
mint = Pubkey.from_string(token_data["mint"])
|
mint = Pubkey.from_string(token_data["mint"])
|
||||||
bonding_curve = Pubkey.from_string(token_data["bondingCurve"])
|
bonding_curve = Pubkey.from_string(token_data["bondingCurve"])
|
||||||
associated_bonding_curve = Pubkey.from_string(token_data["associatedBondingCurve"])
|
associated_bonding_curve = Pubkey.from_string(token_data["associatedBondingCurve"])
|
||||||
|
creator_vault = _find_creator_vault(Pubkey.from_string(token_data["creator"]))
|
||||||
|
|
||||||
# Fetch the token price
|
# Fetch the token price
|
||||||
async with AsyncClient(RPC_ENDPOINT) as client:
|
async with AsyncClient(RPC_ENDPOINT) as client:
|
||||||
@@ -377,7 +398,7 @@ async def main():
|
|||||||
print(
|
print(
|
||||||
f"Buying {amount:.6f} SOL worth of the new token with {slippage * 100:.1f}% slippage tolerance..."
|
f"Buying {amount:.6f} SOL worth of the new token with {slippage * 100:.1f}% slippage tolerance..."
|
||||||
)
|
)
|
||||||
await buy_token(mint, bonding_curve, associated_bonding_curve, amount, slippage)
|
await buy_token(mint, bonding_curve, associated_bonding_curve, creator_vault, amount, slippage)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import os
|
|||||||
import struct
|
import struct
|
||||||
|
|
||||||
import base58
|
import base58
|
||||||
from construct import Flag, Int64ul, Struct
|
from construct import Bytes, Flag, Int64ul, Struct
|
||||||
from solana.rpc.async_api import AsyncClient
|
from solana.rpc.async_api import AsyncClient
|
||||||
from solana.rpc.commitment import Confirmed
|
from solana.rpc.commitment import Confirmed
|
||||||
from solana.rpc.types import TxOpts
|
from solana.rpc.types import TxOpts
|
||||||
@@ -37,7 +37,6 @@ LAMPORTS_PER_SOL = 1_000_000_000
|
|||||||
UNIT_PRICE = 10_000_000
|
UNIT_PRICE = 10_000_000
|
||||||
UNIT_BUDGET = 100_000
|
UNIT_BUDGET = 100_000
|
||||||
|
|
||||||
# RPC endpoint
|
|
||||||
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||||
|
|
||||||
|
|
||||||
@@ -49,12 +48,21 @@ class BondingCurveState:
|
|||||||
"real_sol_reserves" / Int64ul,
|
"real_sol_reserves" / Int64ul,
|
||||||
"token_total_supply" / Int64ul,
|
"token_total_supply" / Int64ul,
|
||||||
"complete" / Flag,
|
"complete" / Flag,
|
||||||
|
"creator" / Bytes(32), # Added new creator field - 32 bytes for Pubkey
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, data: bytes) -> None:
|
def __init__(self, data: bytes) -> None:
|
||||||
|
"""Parse bonding curve data."""
|
||||||
|
if data[:8] != EXPECTED_DISCRIMINATOR:
|
||||||
|
raise ValueError("Invalid curve state discriminator")
|
||||||
|
|
||||||
parsed = self._STRUCT.parse(data[8:])
|
parsed = self._STRUCT.parse(data[8:])
|
||||||
self.__dict__.update(parsed)
|
self.__dict__.update(parsed)
|
||||||
|
|
||||||
|
# Convert raw bytes to Pubkey for creator field
|
||||||
|
if hasattr(self, 'creator') and isinstance(self.creator, bytes):
|
||||||
|
self.creator = Pubkey.from_bytes(self.creator)
|
||||||
|
|
||||||
|
|
||||||
async def get_pump_curve_state(
|
async def get_pump_curve_state(
|
||||||
conn: AsyncClient, curve_address: Pubkey
|
conn: AsyncClient, curve_address: Pubkey
|
||||||
@@ -70,6 +78,33 @@ async def get_pump_curve_state(
|
|||||||
return BondingCurveState(data)
|
return BondingCurveState(data)
|
||||||
|
|
||||||
|
|
||||||
|
def get_bonding_curve_address(mint: Pubkey) -> tuple[Pubkey, int]:
|
||||||
|
return Pubkey.find_program_address([b"bonding-curve", bytes(mint)], PUMP_PROGRAM)
|
||||||
|
|
||||||
|
|
||||||
|
def find_associated_bonding_curve(mint: Pubkey, bonding_curve: Pubkey) -> Pubkey:
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
bytes(bonding_curve),
|
||||||
|
bytes(SYSTEM_TOKEN_PROGRAM),
|
||||||
|
bytes(mint),
|
||||||
|
],
|
||||||
|
SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
|
def find_creator_vault(creator: Pubkey) -> Pubkey:
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"creator-vault",
|
||||||
|
bytes(creator)
|
||||||
|
],
|
||||||
|
PUMP_PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
def calculate_pump_curve_price(curve_state: BondingCurveState) -> float:
|
def calculate_pump_curve_price(curve_state: BondingCurveState) -> float:
|
||||||
if curve_state.virtual_token_reserves <= 0 or curve_state.virtual_sol_reserves <= 0:
|
if curve_state.virtual_token_reserves <= 0 or curve_state.virtual_sol_reserves <= 0:
|
||||||
raise ValueError("Invalid reserve state")
|
raise ValueError("Invalid reserve state")
|
||||||
@@ -90,6 +125,7 @@ async def sell_token(
|
|||||||
mint: Pubkey,
|
mint: Pubkey,
|
||||||
bonding_curve: Pubkey,
|
bonding_curve: Pubkey,
|
||||||
associated_bonding_curve: Pubkey,
|
associated_bonding_curve: Pubkey,
|
||||||
|
creator_vault: Pubkey,
|
||||||
slippage: float = 0.25,
|
slippage: float = 0.25,
|
||||||
max_retries=5,
|
max_retries=5,
|
||||||
):
|
):
|
||||||
@@ -148,9 +184,9 @@ async def sell_token(
|
|||||||
pubkey=SYSTEM_PROGRAM, is_signer=False, is_writable=False
|
pubkey=SYSTEM_PROGRAM, is_signer=False, is_writable=False
|
||||||
),
|
),
|
||||||
AccountMeta(
|
AccountMeta(
|
||||||
pubkey=SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM,
|
pubkey=creator_vault,
|
||||||
is_signer=False,
|
is_signer=False,
|
||||||
is_writable=False,
|
is_writable=True,
|
||||||
),
|
),
|
||||||
AccountMeta(
|
AccountMeta(
|
||||||
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
|
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
|
||||||
@@ -199,17 +235,20 @@ async def sell_token(
|
|||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
# Replace these with the actual values for the token you want to sell
|
# Replace these with the actual values for the token you want to sell
|
||||||
mint = Pubkey.from_string("7aXYndxpkHRU9xg1hyAE6z3X3KYPc2LR3dJMzYTSpump")
|
mint = Pubkey.from_string("5GkGpfvRLusWGqxSkwk7uEs6mHzNxH8QaZD6uPvYpump")
|
||||||
bonding_curve = Pubkey.from_string("5UYdCZigGDyAh1doCW8FdnA7VwJTJePayTLCyZkAWMxg")
|
bonding_curve, _ = get_bonding_curve_address(mint)
|
||||||
associated_bonding_curve = Pubkey.from_string(
|
associated_bonding_curve = find_associated_bonding_curve(mint, bonding_curve)
|
||||||
"BS2RUaPXjQpfzncizvmEfnARZG6SNp1imXnv5USA7PMA"
|
|
||||||
)
|
async with AsyncClient(RPC_ENDPOINT) as client:
|
||||||
|
curve_state = await get_pump_curve_state(client, bonding_curve)
|
||||||
|
|
||||||
|
creator_vault = find_creator_vault(curve_state.creator)
|
||||||
|
|
||||||
slippage = 0.25 # 25% slippage tolerance
|
slippage = 0.25 # 25% slippage tolerance
|
||||||
|
|
||||||
print(f"Bonding curve address: {bonding_curve}")
|
print(f"Bonding curve address: {bonding_curve}")
|
||||||
print(f"Selling tokens with {slippage * 100:.1f}% slippage tolerance...")
|
print(f"Selling tokens with {slippage * 100:.1f}% slippage tolerance...")
|
||||||
await sell_token(mint, bonding_curve, associated_bonding_curve, slippage)
|
await sell_token(mint, bonding_curve, associated_bonding_curve, creator_vault, slippage)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ async def get_market_data(market_address: Pubkey):
|
|||||||
("pool_base_token_account", "pubkey"),
|
("pool_base_token_account", "pubkey"),
|
||||||
("pool_quote_token_account", "pubkey"),
|
("pool_quote_token_account", "pubkey"),
|
||||||
("lp_supply", "u64"),
|
("lp_supply", "u64"),
|
||||||
|
("coin_creator", "pubkey"),
|
||||||
]
|
]
|
||||||
|
|
||||||
for field_name, field_type in fields:
|
for field_name, field_type in fields:
|
||||||
|
|||||||
@@ -0,0 +1,323 @@
|
|||||||
|
"""
|
||||||
|
Solana PUMP AMM Interface
|
||||||
|
|
||||||
|
This module provides functionality to interact with the PUMP AMM program on Solana, enabling:
|
||||||
|
- Finding market addresses by token mint
|
||||||
|
- Fetching and parsing market data from PUMP AMM pools
|
||||||
|
- Calculating token prices in AMM pools
|
||||||
|
- Creating associated token accounts (ATAs) idempotently
|
||||||
|
- Buying tokens on the PUMP AMM with slippage protection
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
|
||||||
|
import base58
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from solana.rpc.async_api import AsyncClient
|
||||||
|
from solana.rpc.commitment import Confirmed
|
||||||
|
from solana.rpc.types import MemcmpOpts, TxOpts
|
||||||
|
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
|
||||||
|
from solders.instruction import AccountMeta, Instruction
|
||||||
|
from solders.keypair import Keypair
|
||||||
|
from solders.message import Message
|
||||||
|
from solders.pubkey import Pubkey
|
||||||
|
from solders.transaction import VersionedTransaction
|
||||||
|
from spl.token.instructions import (
|
||||||
|
create_idempotent_associated_token_account,
|
||||||
|
get_associated_token_address,
|
||||||
|
)
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Configuration constants
|
||||||
|
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||||
|
TOKEN_MINT = Pubkey.from_string("...")
|
||||||
|
PRIVATE_KEY = base58.b58decode(os.environ.get("SOLANA_PRIVATE_KEY"))
|
||||||
|
PAYER = Keypair.from_bytes(PRIVATE_KEY)
|
||||||
|
SLIPPAGE = 0.3 # Slippage tolerance (30%) - the maximum price movement you'll accept
|
||||||
|
|
||||||
|
TOKEN_DECIMALS = 6
|
||||||
|
BUY_DISCRIMINATOR = bytes.fromhex("66063d1201daebea") # Program instruction identifier for the buy function
|
||||||
|
|
||||||
|
# Solana system addresses and program IDs
|
||||||
|
SOL = Pubkey.from_string("So11111111111111111111111111111111111111112")
|
||||||
|
PUMP_AMM_PROGRAM_ID = Pubkey.from_string("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA")
|
||||||
|
PUMP_SWAP_GLOBAL_CONFIG = Pubkey.from_string("ADyA8hdefvWN2dbGGWFotbzWxrAvLW83WG6QCVXvJKqw")
|
||||||
|
PUMP_PROTOCOL_FEE_RECIPIENT = Pubkey.from_string("7VtfL8fvgNfhz17qKRMjzQEXgbdpnHHHQRh54R9jP2RJ")
|
||||||
|
PUMP_PROTOCOL_FEE_RECIPIENT_TOKEN_ACCOUNT = Pubkey.from_string("7GFUN3bWzJMKMRZ34JLsvcqdssDbXnp589SiE33KVwcC")
|
||||||
|
SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
|
||||||
|
SYSTEM_PROGRAM = Pubkey.from_string("11111111111111111111111111111111")
|
||||||
|
SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL")
|
||||||
|
PUMP_SWAP_EVENT_AUTHORITY = Pubkey.from_string("GS4CU59F31iL7aR2Q8zVS8DRrcRnXX1yjQ66TqNVQnaR")
|
||||||
|
LAMPORTS_PER_SOL = 1_000_000_000
|
||||||
|
COMPUTE_UNIT_PRICE = 10_000 # Price in micro-lamports per compute unit
|
||||||
|
COMPUTE_UNIT_BUDGET = 100_000 # Maximum compute units to use
|
||||||
|
|
||||||
|
|
||||||
|
async def get_market_address_by_base_mint(client: AsyncClient, base_mint_address: Pubkey, amm_program_id: Pubkey) -> Pubkey:
|
||||||
|
"""Find the market address for a given token mint.
|
||||||
|
|
||||||
|
Searches for the AMM pool that contains the specified token mint as its base token
|
||||||
|
by querying program accounts with a filter for the base_mint field.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
client: Solana RPC client instance
|
||||||
|
base_mint_address: Address of the token mint you want to find the market for
|
||||||
|
amm_program_id: Address of the AMM program
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The Pubkey of the market (AMM pool) for the token
|
||||||
|
"""
|
||||||
|
base_mint_bytes = bytes(base_mint_address)
|
||||||
|
offset = 43 # Offset where the base_mint field is stored in the account data structure
|
||||||
|
filters = [
|
||||||
|
MemcmpOpts(offset=offset, bytes=base_mint_bytes)
|
||||||
|
]
|
||||||
|
|
||||||
|
response = await client.get_program_accounts(
|
||||||
|
amm_program_id,
|
||||||
|
encoding="base64",
|
||||||
|
filters=filters
|
||||||
|
)
|
||||||
|
|
||||||
|
market_address = [account.pubkey for account in response.value][0]
|
||||||
|
return market_address
|
||||||
|
|
||||||
|
async def get_market_data(client: AsyncClient, market_address: Pubkey) -> dict:
|
||||||
|
"""Fetch and parse market data from the blockchain.
|
||||||
|
|
||||||
|
Retrieves and deserializes the binary data stored in the market account
|
||||||
|
into a structured dictionary containing key market information.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
client: Solana RPC client instance
|
||||||
|
market_address: Address of the market (AMM pool) to fetch data for
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary containing the parsed market data
|
||||||
|
"""
|
||||||
|
response = await client.get_account_info(market_address, encoding="base64")
|
||||||
|
data = response.value.data
|
||||||
|
parsed_data: dict = {}
|
||||||
|
|
||||||
|
# Start after the 8-byte discriminator
|
||||||
|
offset = 8
|
||||||
|
# Define the structure of the market account data
|
||||||
|
fields = [
|
||||||
|
("pool_bump", "u8"),
|
||||||
|
("index", "u16"),
|
||||||
|
("creator", "pubkey"),
|
||||||
|
("base_mint", "pubkey"),
|
||||||
|
("quote_mint", "pubkey"),
|
||||||
|
("lp_mint", "pubkey"),
|
||||||
|
("pool_base_token_account", "pubkey"),
|
||||||
|
("pool_quote_token_account", "pubkey"),
|
||||||
|
("lp_supply", "u64"),
|
||||||
|
("coin_creator", "pubkey")
|
||||||
|
]
|
||||||
|
|
||||||
|
for field_name, field_type in fields:
|
||||||
|
if field_type == "pubkey":
|
||||||
|
value = data[offset:offset + 32]
|
||||||
|
parsed_data[field_name] = base58.b58encode(value).decode("utf-8")
|
||||||
|
offset += 32
|
||||||
|
elif field_type in {"u64", "i64"}:
|
||||||
|
value = struct.unpack("<Q", data[offset:offset + 8])[0] if field_type == "u64" else struct.unpack("<q", data[offset:offset + 8])[0]
|
||||||
|
parsed_data[field_name] = value
|
||||||
|
offset += 8
|
||||||
|
elif field_type == "u16":
|
||||||
|
value = struct.unpack("<H", data[offset:offset + 2])[0]
|
||||||
|
parsed_data[field_name] = value
|
||||||
|
offset += 2
|
||||||
|
elif field_type == "u8":
|
||||||
|
value = data[offset]
|
||||||
|
parsed_data[field_name] = value
|
||||||
|
offset += 1
|
||||||
|
|
||||||
|
return parsed_data
|
||||||
|
|
||||||
|
def find_coin_creator_vault(coin_creator: Pubkey) -> Pubkey:
|
||||||
|
"""Derive the Program Derived Address (PDA) for a coin creator's vault.
|
||||||
|
|
||||||
|
Calculates the deterministic PDA that serves as the vault authority
|
||||||
|
for a specific coin creator in the PUMP AMM protocol.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
coin_creator: Pubkey of the coin creator account
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Pubkey of the derived coin creator vault authority
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This vault is used to collect creator fees from token transactions
|
||||||
|
"""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"creator_vault",
|
||||||
|
bytes(coin_creator)
|
||||||
|
],
|
||||||
|
PUMP_AMM_PROGRAM_ID,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
async def calculate_token_pool_price(client: AsyncClient, pool_base_token_account: Pubkey, pool_quote_token_account: Pubkey) -> float:
|
||||||
|
"""Calculate the current price of tokens in an AMM pool.
|
||||||
|
|
||||||
|
Fetches the balance of tokens in the pool and calculates the price ratio
|
||||||
|
between the base token and quote token (typically SOL).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
client: Solana RPC client instance
|
||||||
|
pool_base_token_account: Address of the pool's base token account (your token)
|
||||||
|
pool_quote_token_account: Address of the pool's quote token account (SOL)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The price of the base token in terms of the quote token (SOL per token)
|
||||||
|
"""
|
||||||
|
base_balance_resp = await client.get_token_account_balance(pool_base_token_account)
|
||||||
|
quote_balance_resp = await client.get_token_account_balance(pool_quote_token_account)
|
||||||
|
|
||||||
|
# Extract the UI amounts (human-readable with decimals)
|
||||||
|
base_amount = float(base_balance_resp.value.ui_amount)
|
||||||
|
quote_amount = float(quote_balance_resp.value.ui_amount)
|
||||||
|
|
||||||
|
token_price = quote_amount / base_amount
|
||||||
|
|
||||||
|
return token_price
|
||||||
|
|
||||||
|
async def buy_pump_swap(client: AsyncClient, pump_fun_amm_market: Pubkey, payer: Keypair,
|
||||||
|
base_mint: Pubkey, user_base_token_account: Pubkey,
|
||||||
|
user_quote_token_account: Pubkey, pool_base_token_account: Pubkey,
|
||||||
|
pool_quote_token_account: Pubkey, coin_creator_vault_authority: Pubkey,
|
||||||
|
coin_creator_vault_ata: Pubkey, sol_amount_to_spend: int, slippage: float = 0.25) -> str | None:
|
||||||
|
"""Buy tokens on the PUMP AMM with slippage protection.
|
||||||
|
|
||||||
|
Executes a token purchase on the PUMP AMM protocol, calculating the expected
|
||||||
|
token amount based on the current pool price and applying slippage protection.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
client: Solana RPC client instance
|
||||||
|
pump_fun_amm_market: Address of the AMM market
|
||||||
|
payer: Keypair of the transaction signer and token buyer
|
||||||
|
base_mint: Address of the token mint being purchased
|
||||||
|
user_base_token_account: Address of the user's token account for receiving purchased tokens
|
||||||
|
user_quote_token_account: Address of the user's SOL token account
|
||||||
|
pool_base_token_account: Address of the pool's token account for the token being purchased
|
||||||
|
pool_quote_token_account: Address of the pool's SOL token account
|
||||||
|
coin_creator_vault_authority: Address of the coin creator's vault authority
|
||||||
|
coin_creator_vault_ata: Address of the coin creator's associated token account for fees
|
||||||
|
sol_amount_to_spend: Amount of SOL to spend on the purchase (in SOL, not lamports)
|
||||||
|
slippage: Maximum acceptable price slippage, as a decimal (0.25 = 25%)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Transaction signature if successful, None otherwise
|
||||||
|
"""
|
||||||
|
# Calculate token price
|
||||||
|
token_price_sol = await calculate_token_pool_price(client, pool_base_token_account, pool_quote_token_account)
|
||||||
|
print(f"Token price in SOL: {token_price_sol:.10f} SOL")
|
||||||
|
|
||||||
|
# Calculate maximum SOL input with slippage protection
|
||||||
|
base_amount_out = int((sol_amount_to_spend / token_price_sol) * 10**TOKEN_DECIMALS)
|
||||||
|
slippage_factor = 1 + slippage
|
||||||
|
max_sol_input = int((sol_amount_to_spend * slippage_factor) * LAMPORTS_PER_SOL)
|
||||||
|
|
||||||
|
print(f"Buying {base_amount_out / (10**TOKEN_DECIMALS):.10f} tokens")
|
||||||
|
print(f"Maximum SOL input: {max_sol_input / LAMPORTS_PER_SOL:.10f} SOL")
|
||||||
|
|
||||||
|
# Define all accounts needed for the buy instruction
|
||||||
|
accounts = [
|
||||||
|
AccountMeta(pubkey=pump_fun_amm_market, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=payer.pubkey(), is_signer=True, is_writable=True),
|
||||||
|
AccountMeta(pubkey=PUMP_SWAP_GLOBAL_CONFIG, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=base_mint, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=SOL, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=user_base_token_account, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=user_quote_token_account, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=pool_base_token_account, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=pool_quote_token_account, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=PUMP_PROTOCOL_FEE_RECIPIENT, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=PUMP_PROTOCOL_FEE_RECIPIENT_TOKEN_ACCOUNT, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=SYSTEM_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=PUMP_SWAP_EVENT_AUTHORITY, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=PUMP_AMM_PROGRAM_ID, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=coin_creator_vault_ata, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=coin_creator_vault_authority, is_signer=False, is_writable=False),
|
||||||
|
]
|
||||||
|
|
||||||
|
data = BUY_DISCRIMINATOR + struct.pack("<Q", base_amount_out) + struct.pack("<Q", max_sol_input)
|
||||||
|
|
||||||
|
compute_limit_ix = set_compute_unit_limit(COMPUTE_UNIT_BUDGET)
|
||||||
|
compute_price_ix = set_compute_unit_price(COMPUTE_UNIT_PRICE)
|
||||||
|
|
||||||
|
idempotent_ata_ix = create_idempotent_associated_token_account(
|
||||||
|
payer.pubkey(),
|
||||||
|
payer.pubkey(),
|
||||||
|
base_mint,
|
||||||
|
SYSTEM_TOKEN_PROGRAM
|
||||||
|
)
|
||||||
|
|
||||||
|
buy_ix = Instruction(PUMP_AMM_PROGRAM_ID, data, accounts)
|
||||||
|
|
||||||
|
blockhash_resp = await client.get_latest_blockhash()
|
||||||
|
recent_blockhash = blockhash_resp.value.blockhash
|
||||||
|
|
||||||
|
msg = Message.new_with_blockhash(
|
||||||
|
[compute_limit_ix, compute_price_ix, idempotent_ata_ix, buy_ix],
|
||||||
|
payer.pubkey(),
|
||||||
|
recent_blockhash
|
||||||
|
)
|
||||||
|
|
||||||
|
tx_buy = VersionedTransaction(
|
||||||
|
message=msg,
|
||||||
|
keypairs=[payer]
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
tx_sig = await client.send_transaction(
|
||||||
|
tx_buy,
|
||||||
|
opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed),
|
||||||
|
)
|
||||||
|
|
||||||
|
tx_hash = tx_sig.value
|
||||||
|
print(f"Transaction sent: https://explorer.solana.com/tx/{tx_hash}")
|
||||||
|
await client.confirm_transaction(tx_hash, commitment="confirmed")
|
||||||
|
|
||||||
|
print("Transaction confirmed")
|
||||||
|
return tx_hash
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error sending transaction: {e!s}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
"""Main function to execute the token buying process."""
|
||||||
|
sol_amount_to_spend = 0.000001
|
||||||
|
|
||||||
|
async with AsyncClient(RPC_ENDPOINT) as client:
|
||||||
|
market_address = await get_market_address_by_base_mint(client, TOKEN_MINT, PUMP_AMM_PROGRAM_ID)
|
||||||
|
market_data = await get_market_data(client, market_address)
|
||||||
|
coin_creator_vault_authority = find_coin_creator_vault(Pubkey.from_string(market_data["coin_creator"]))
|
||||||
|
coin_creator_vault_ata = get_associated_token_address(coin_creator_vault_authority, SOL)
|
||||||
|
|
||||||
|
await buy_pump_swap(
|
||||||
|
client,
|
||||||
|
market_address,
|
||||||
|
PAYER,
|
||||||
|
TOKEN_MINT,
|
||||||
|
get_associated_token_address(PAYER.pubkey(), TOKEN_MINT),
|
||||||
|
get_associated_token_address(PAYER.pubkey(), SOL),
|
||||||
|
Pubkey.from_string(market_data["pool_base_token_account"]),
|
||||||
|
Pubkey.from_string(market_data["pool_quote_token_account"]),
|
||||||
|
coin_creator_vault_authority,
|
||||||
|
coin_creator_vault_ata,
|
||||||
|
sol_amount_to_spend,
|
||||||
|
SLIPPAGE,
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
@@ -28,7 +28,7 @@ load_dotenv()
|
|||||||
|
|
||||||
# Configuration constants
|
# Configuration constants
|
||||||
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||||
TOKEN_MINT = Pubkey.from_string("8XNrSusWrzYpizYXJb5yeB66AWX1cfQ86SBJFqVTpump")
|
TOKEN_MINT = Pubkey.from_string("...")
|
||||||
PRIVATE_KEY = base58.b58decode(os.environ.get("SOLANA_PRIVATE_KEY"))
|
PRIVATE_KEY = base58.b58decode(os.environ.get("SOLANA_PRIVATE_KEY"))
|
||||||
PAYER = Keypair.from_bytes(PRIVATE_KEY)
|
PAYER = Keypair.from_bytes(PRIVATE_KEY)
|
||||||
SLIPPAGE = 0.25 # Slippage tolerance (25%) - the maximum price movement you'll accept
|
SLIPPAGE = 0.25 # Slippage tolerance (25%) - the maximum price movement you'll accept
|
||||||
@@ -108,6 +108,7 @@ async def get_market_data(client: AsyncClient, market_address: Pubkey) -> dict:
|
|||||||
("pool_base_token_account", "pubkey"),
|
("pool_base_token_account", "pubkey"),
|
||||||
("pool_quote_token_account", "pubkey"),
|
("pool_quote_token_account", "pubkey"),
|
||||||
("lp_supply", "u64"),
|
("lp_supply", "u64"),
|
||||||
|
("coin_creator", "pubkey")
|
||||||
]
|
]
|
||||||
|
|
||||||
for field_name, field_type in fields:
|
for field_name, field_type in fields:
|
||||||
@@ -130,6 +131,30 @@ async def get_market_data(client: AsyncClient, market_address: Pubkey) -> dict:
|
|||||||
|
|
||||||
return parsed_data
|
return parsed_data
|
||||||
|
|
||||||
|
def find_coin_creator_vault(coin_creator: Pubkey) -> Pubkey:
|
||||||
|
"""Derive the Program Derived Address (PDA) for a coin creator's vault.
|
||||||
|
|
||||||
|
Calculates the deterministic PDA that serves as the vault authority
|
||||||
|
for a specific coin creator in the PUMP AMM protocol.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
coin_creator: Pubkey of the coin creator account
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Pubkey of the derived coin creator vault authority
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This vault is used to collect creator fees from token transactions
|
||||||
|
"""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"creator_vault",
|
||||||
|
bytes(coin_creator)
|
||||||
|
],
|
||||||
|
PUMP_AMM_PROGRAM_ID,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
async def calculate_token_pool_price(client: AsyncClient, pool_base_token_account: Pubkey, pool_quote_token_account: Pubkey) -> float:
|
async def calculate_token_pool_price(client: AsyncClient, pool_base_token_account: Pubkey, pool_quote_token_account: Pubkey) -> float:
|
||||||
"""Calculate the price of tokens in the pool.
|
"""Calculate the price of tokens in the pool.
|
||||||
|
|
||||||
@@ -186,7 +211,8 @@ def create_ata_idempotent_ix(payer_pubkey: Pubkey) -> Instruction:
|
|||||||
async def sell_pump_swap(client: AsyncClient, pump_fun_amm_market: Pubkey, payer: Keypair,
|
async def sell_pump_swap(client: AsyncClient, pump_fun_amm_market: Pubkey, payer: Keypair,
|
||||||
base_mint: Pubkey, user_base_token_account: Pubkey,
|
base_mint: Pubkey, user_base_token_account: Pubkey,
|
||||||
user_quote_token_account: Pubkey, pool_base_token_account: Pubkey,
|
user_quote_token_account: Pubkey, pool_base_token_account: Pubkey,
|
||||||
pool_quote_token_account: Pubkey, slippage: float = 0.25) -> str | None:
|
pool_quote_token_account: Pubkey, coin_creator_vault_authority: Pubkey,
|
||||||
|
coin_creator_vault_ata: Pubkey, slippage: float = 0.25) -> str | None:
|
||||||
"""Sell tokens on the PUMP AMM.
|
"""Sell tokens on the PUMP AMM.
|
||||||
|
|
||||||
This function sells all tokens in the user's token account with the specified slippage tolerance.
|
This function sells all tokens in the user's token account with the specified slippage tolerance.
|
||||||
@@ -200,6 +226,8 @@ async def sell_pump_swap(client: AsyncClient, pump_fun_amm_market: Pubkey, payer
|
|||||||
user_quote_token_account: Address of the user's SOL token account
|
user_quote_token_account: Address of the user's SOL token account
|
||||||
pool_base_token_account: Address of the pool's token account for the token being sold
|
pool_base_token_account: Address of the pool's token account for the token being sold
|
||||||
pool_quote_token_account: Address of the pool's SOL token account
|
pool_quote_token_account: Address of the pool's SOL token account
|
||||||
|
coin_creator_vault_authority: Address of the coin creator's vault authority
|
||||||
|
coin_creator_vault_ata: Address of the coin creator's associated token account for fees
|
||||||
slippage: Maximum acceptable price slippage, as a decimal (0.25 = 25%)
|
slippage: Maximum acceptable price slippage, as a decimal (0.25 = 25%)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -245,6 +273,8 @@ async def sell_pump_swap(client: AsyncClient, pump_fun_amm_market: Pubkey, payer
|
|||||||
AccountMeta(pubkey=SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM, is_signer=False, is_writable=False),
|
||||||
AccountMeta(pubkey=PUMP_SWAP_EVENT_AUTHORITY, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=PUMP_SWAP_EVENT_AUTHORITY, is_signer=False, is_writable=False),
|
||||||
AccountMeta(pubkey=PUMP_AMM_PROGRAM_ID, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=PUMP_AMM_PROGRAM_ID, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=coin_creator_vault_ata, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=coin_creator_vault_authority, is_signer=False, is_writable=False),
|
||||||
]
|
]
|
||||||
|
|
||||||
data = SELL_DISCRIMINATOR + struct.pack("<Q", amount) + struct.pack("<Q", min_sol_output)
|
data = SELL_DISCRIMINATOR + struct.pack("<Q", amount) + struct.pack("<Q", min_sol_output)
|
||||||
@@ -294,6 +324,8 @@ async def main():
|
|||||||
async with AsyncClient(RPC_ENDPOINT) as client:
|
async with AsyncClient(RPC_ENDPOINT) as client:
|
||||||
market_address = await get_market_address_by_base_mint(client, TOKEN_MINT, PUMP_AMM_PROGRAM_ID)
|
market_address = await get_market_address_by_base_mint(client, TOKEN_MINT, PUMP_AMM_PROGRAM_ID)
|
||||||
market_data = await get_market_data(client, market_address)
|
market_data = await get_market_data(client, market_address)
|
||||||
|
coin_creator_vault_authority = find_coin_creator_vault(Pubkey.from_string(market_data["coin_creator"]))
|
||||||
|
coin_creator_vault_ata = get_associated_token_address(coin_creator_vault_authority, SOL)
|
||||||
|
|
||||||
await sell_pump_swap(
|
await sell_pump_swap(
|
||||||
client,
|
client,
|
||||||
@@ -304,6 +336,8 @@ async def main():
|
|||||||
get_associated_token_address(PAYER.pubkey(), SOL),
|
get_associated_token_address(PAYER.pubkey(), SOL),
|
||||||
Pubkey.from_string(market_data["pool_base_token_account"]),
|
Pubkey.from_string(market_data["pool_base_token_account"]),
|
||||||
Pubkey.from_string(market_data["pool_quote_token_account"]),
|
Pubkey.from_string(market_data["pool_quote_token_account"]),
|
||||||
|
coin_creator_vault_authority,
|
||||||
|
coin_creator_vault_ata,
|
||||||
SLIPPAGE
|
SLIPPAGE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user