Skip to content

Commit

Permalink
More changes required for HIP-138
Browse files Browse the repository at this point in the history
  • Loading branch information
ChewingGlass committed Nov 11, 2024
1 parent 0c35ef8 commit aab65bf
Show file tree
Hide file tree
Showing 11 changed files with 279 additions and 65 deletions.
114 changes: 60 additions & 54 deletions packages/crons/src/end-epoch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,72 +270,78 @@ async function getSolanaUnixTimestamp(connection: Connection): Promise<bigint> {
const hemProgram = await initHem(provider);
const lazyProgram = await initLazy(provider);
const rewardsOracleProgram = await initRewards(provider);
const [lazyDistributor] = lazyDistributorKey(iotMint);
const [keyToAsset] = keyToAssetKey(dao, IOT_OPERATIONS_FUND, "utf8");
const assetId = (await hemProgram.account.keyToAssetV0.fetch(keyToAsset))
.asset;

const [recipient] = recipientKey(lazyDistributor, assetId);
if (!(await provider.connection.getAccountInfo(recipient))) {
const method = lazyProgram.methods.initializeRecipientV0().accounts({
lazyDistributor,
mint: assetId,
});

await sendInstructionsWithPriorityFee(provider, [await method.instruction()], {
basePriorityFee: BASE_PRIORITY_FEE
});
}
for (const token of [IOT_MINT, HNT_MINT]) {
const [lazyDistributor] = lazyDistributorKey(token);
const [keyToAsset] = keyToAssetKey(dao, IOT_OPERATIONS_FUND, "utf8");
const assetId = (await hemProgram.account.keyToAssetV0.fetch(keyToAsset))
.asset;

const [recipient] = recipientKey(lazyDistributor, assetId);
if (!(await provider.connection.getAccountInfo(recipient))) {
const method = lazyProgram.methods.initializeRecipientV0().accounts({
lazyDistributor,
mint: assetId,
});

await sendInstructionsWithPriorityFee(
provider,
[await method.instruction()],
{
basePriorityFee: BASE_PRIORITY_FEE,
}
);
}

const rewards = await client.getCurrentRewards(
lazyProgram,
lazyDistributor,
assetId
);
const rewards = await client.getCurrentRewards(
lazyProgram,
lazyDistributor,
assetId
);

const pending = await client.getPendingRewards(
lazyProgram,
lazyDistributor,
daoKey(HNT_MINT)[0],
[IOT_OPERATIONS_FUND],
"utf8"
);
const pending = await client.getPendingRewards(
lazyProgram,
lazyDistributor,
daoKey(HNT_MINT)[0],
[IOT_OPERATIONS_FUND],
"utf8"
);

// Avoid claiming too much and tripping the breaker
if (new BN(pending[IOT_OPERATIONS_FUND]).gt(MAX_CLAIM_AMOUNT)) {
rewards[0].currentRewards = new BN(rewards[0].currentRewards)
.sub(new BN(pending[IOT_OPERATIONS_FUND]))
.add(MAX_CLAIM_AMOUNT)
.toString();
}
// Avoid claiming too much and tripping the breaker
if (new BN(pending[IOT_OPERATIONS_FUND]).gt(MAX_CLAIM_AMOUNT)) {
rewards[0].currentRewards = new BN(rewards[0].currentRewards)
.sub(new BN(pending[IOT_OPERATIONS_FUND]))
.add(MAX_CLAIM_AMOUNT)
.toString();
}

const tx = await client.formTransaction({
program: lazyProgram,
rewardsOracleProgram: rewardsOracleProgram,
provider,
rewards,
asset: assetId,
lazyDistributor,
});
const tx = await client.formTransaction({
program: lazyProgram,
rewardsOracleProgram: rewardsOracleProgram,
provider,
rewards,
asset: assetId,
lazyDistributor,
});

const signed = await provider.wallet.signTransaction(tx);
const signed = await provider.wallet.signTransaction(tx);

try {
await sendAndConfirmWithRetry(
provider.connection,
Buffer.from(signed.serialize()),
{ skipPreflight: true },
"confirmed"
);
} catch (err: any) {
errors.push(`Failed to distribute iot op funds: ${err}`);
try {
await sendAndConfirmWithRetry(
provider.connection,
Buffer.from(signed.serialize()),
{ skipPreflight: true },
"confirmed"
);
} catch (err: any) {
errors.push(`Failed to distribute iot op funds: ${err}`);
}
}

// Only do this if that feature has been deployed
if (hemProgram.methods.issueNotEmittedEntityV0) {
console.log("Issuing no_emit");
const noEmitProgram = await initBurn(provider);
const tokens = [MOBILE_MINT, IOT_MINT];
const tokens = [MOBILE_MINT, IOT_MINT, HNT_MINT];
for (const token of tokens) {
const [lazyDistributor] = lazyDistributorKey(token);
const notEmittedEntityKta = keyToAssetKey(dao, NOT_EMITTED, "utf-8")[0];
Expand Down
12 changes: 4 additions & 8 deletions packages/helium-admin-cli/emissions/hst.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
[
{
"startTime": "2023-04-18T00:00:00Z",
"percent": 32
},
{
"startTime": "2023-08-01T00:00:00Z",
"percent": 31
},
{
"startTime": "2024-08-01T00:00:01Z",
"percent": 30
},
{
"startTime": "2025-08-01T00:00:01Z",
"percent": 0
}
]
1 change: 1 addition & 0 deletions packages/helium-admin-cli/src/create-subdao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ export async function run(args: any = process.argv) {
registrar: null,
delegatorRewardsPercent: null,
activeDeviceAuthority: null,
rewardsEscrow: null
})
.accounts({
subDao,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export async function run(args: any = process.argv) {
registrar: null,
delegatorRewardsPercent: null,
activeDeviceAuthority: null,
rewardsEscrow: null,
})
.accounts({
subDao,
Expand Down
196 changes: 196 additions & 0 deletions packages/helium-admin-cli/src/migrate-to-hip-138.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import * as anchor from "@coral-xyz/anchor";
import { init as initLazy } from "@helium/lazy-distributor-sdk";
import {
daoKey,
init as initHsd,
subDaoKey,
} from "@helium/helium-sub-daos-sdk";
import { HNT_MINT, IOT_MINT, MOBILE_MINT } from "@helium/spl-utils";
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import Squads from "@sqds/sdk";
import os from "os";
import yargs from "yargs/yargs";
import { loadKeypair, parseEmissionsSchedule, sendInstructionsOrSquads } from "./utils";
import { lazyDistributorKey } from "@helium/lazy-distributor-sdk";
import { ThresholdType } from "@helium/circuit-breaker-sdk";
import { oracleSignerKey } from "@helium/rewards-oracle-sdk";
import { getAssociatedTokenAddressSync } from "@solana/spl-token";

export async function run(args: any = process.argv) {
const yarg = yargs(args).options({
wallet: {
alias: "k",
describe: "Anchor wallet keypair",
default: `${os.homedir()}/.config/solana/id.json`,
},
url: {
alias: "u",
default: "http://127.0.0.1:8899",
describe: "The solana url",
},
iotMint: {
type: "string",
describe: "IOT mint of the subdao to migrate",
default: IOT_MINT.toBase58(),
},
hntMint: {
type: "string",
describe: "HNT mint of the subdao to migrate",
default: HNT_MINT.toBase58(),
},
mobileMint: {
type: "string",
describe: "Mobile mint of the subdao to migrate",
default: MOBILE_MINT.toBase58(),
},
rewardsOracleUrl: {
alias: "ro",
type: "string",
describe: "The rewards oracle URL",
required: true,
},
oracleKey: {
type: "string",
describe: "Pubkey of the oracle",
required: true,
},
emissionSchedulePath: {
required: true,
describe: "Path to file that contains the hnt emissions schedule",
type: "string",
},
hstEmissionsSchedulePath: {
required: true,
describe: "Path to file that contains the new HST emissions schedule",
type: "string",
},
executeTransaction: {
type: "boolean",
},
multisig: {
type: "string",
describe:
"Address of the squads multisig to be authority. If not provided, your wallet will be the authority",
},
authorityIndex: {
type: "number",
describe: "Authority index for squads. Defaults to 1",
default: 1,
},
});
const argv = await yarg.argv;
process.env.ANCHOR_WALLET = argv.wallet;
process.env.ANCHOR_PROVIDER_URL = argv.url;
anchor.setProvider(anchor.AnchorProvider.local(argv.url));
const provider = anchor.getProvider() as anchor.AnchorProvider;
const wallet = new anchor.Wallet(loadKeypair(argv.wallet));
const lazyDistProgram = await initLazy(provider);
const hsdProgram = await initHsd(provider);

const instructions: TransactionInstruction[] = [];

const iotMint = new PublicKey(argv.iotMint);
const mobileMint = new PublicKey(argv.mobileMint);
const hntMint = new PublicKey(argv.hntMint);
const iotSubDao = subDaoKey(iotMint)[0];
const mobileSubDao = subDaoKey(mobileMint)[0];
const dao = daoKey(hntMint)[0];
const daoAcc = await hsdProgram.account.daoV0.fetch(dao);
const authority = daoAcc.authority;
const oracleKey = new PublicKey(argv.oracleKey!);
const emissionSchedule = await parseEmissionsSchedule(
argv.emissionSchedulePath
);

const ld = lazyDistributorKey(hntMint)[0];
const rewardsEscrow = getAssociatedTokenAddressSync(hntMint, ld, true);
const ldAcc = await lazyDistProgram.account.lazyDistributorV0.fetchNullable(ld);
if (ldAcc) {
console.warn("Lazy distributor already exists, skipping.");
} else {
instructions.push(
await lazyDistProgram.methods
.initializeLazyDistributorV0({
authority: daoAcc.authority,
oracles: [
{
oracle: oracleKey,
url: argv.rewardsOracleUrl,
},
],
// 5 x epoch rewards in a 24 hour period
windowConfig: {
windowSizeSeconds: new anchor.BN(24 * 60 * 60),
thresholdType: ThresholdType.Absolute as never,
threshold: new anchor.BN(emissionSchedule[0].emissionsPerEpoch).mul(
new anchor.BN(5)
),
},
approver: oracleSignerKey()[0],
})
.accounts({
payer: authority,
rewardsMint: hntMint,
})
.instruction()
);
}

for (const subDao of [iotSubDao, mobileSubDao]) {
instructions.push(
await hsdProgram.methods
.updateSubDaoV0({
vetokenTracker: null,
votingRewardsPercent: null,
authority: null,
emissionSchedule: null,
dcBurnAuthority: null,
onboardingDcFee: null,
onboardingDataOnlyDcFee: null,
registrar: null,
delegatorRewardsPercent: null,
activeDeviceAuthority: null,
rewardsEscrow,
})
.accounts({
payer: authority,
authority,
subDao,
})
.instruction()
);
}

instructions.push(
await hsdProgram.methods
.updateDaoV0({
authority: null,
emissionSchedule: null,
hstEmissionSchedule: await parseEmissionsSchedule(
argv.hstEmissionsSchedulePath!
),
netEmissionsCap: null,
hstPool: null,
})
.accounts({
dao,
authority: daoAcc.authority,
payer: daoAcc.authority,
})
.instruction()
);

const squads = Squads.endpoint(process.env.ANCHOR_PROVIDER_URL, wallet, {
commitmentOrConfig: "finalized",
});

await sendInstructionsOrSquads({
provider,
instructions,
executeTransaction: argv.executeTransaction,
squads,
multisig: argv.multisig ? new PublicKey(argv.multisig) : undefined,
authorityIndex: argv.authorityIndex,
signers: [],
});
}
1 change: 1 addition & 0 deletions packages/helium-admin-cli/src/update-subdao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export async function run(args: any = process.argv) {
instructions.push(
await program.methods
.updateSubDaoV0({
rewardsEscrow: null,
vetokenTracker: null,
votingRewardsPercent: null,
authority: argv.newAuthority ? new PublicKey(argv.newAuthority) : null,
Expand Down
Loading

0 comments on commit aab65bf

Please sign in to comment.