Rate Limits
How to implement rate limits?
Interactive Simulation
Implementation
const RATE_LIMIT = inputRateLimit;
const RATE_LIMIT_K2 = inputRateLimitK2;
const state = {
valuesRaw: {
carbon: 1100, // tCO2eq
kvcmAlloc: 200_000, // kVCM
k2Alloc: 200_000, // K2
kvcmTotal: 1_000_000, // kVCM
k2Total: 1_000_000, // K2
},
snapshots: {
carbon: { value: 1100, time: 0, rate: RATE_LIMIT },
kvcmAlloc: { value: 200_000, time: 0, rate: RATE_LIMIT },
k2Alloc: { value: 200_000, time: 0, rate: RATE_LIMIT_K2 },
kvcmTotal: { value: 1_000_000, time: 0, rate: RATE_LIMIT },
k2Total: { value: 1_000_000, time: 0, rate: RATE_LIMIT_K2 },
},
time: 0, // hours
};
const carbonDelta = +100; // tCO2eq
const time = 24; // hours
function executeSwap(state, carbonDelta, time) {
const { valuesRaw, snapshots } = state;
const valuesEffective = computeEffectiveValues(valuesRaw, snapshots, time);
const kvcmDelta = computePriceSwap(valuesEffective, carbonDelta);
const stateNew = {
valuesRaw: {
...valuesRaw,
carbon: valuesRaw.carbon + carbonDelta,
kvcmTotal: valuesRaw.kvcmTotal + kvcmDelta,
},
snapshots,
time,
};
return stateNew;
}
function executeRetire(state, carbonDelta, time) {
const { valuesRaw, snapshots } = state;
const valuesEffective = computeEffectiveValues(valuesRaw, snapshots, time);
const valuesRetirement = { ...valuesEffective, carbon: valuesRaw.carbon };
const kvcmDelta = computePriceRetire(valuesRetirement, carbonDelta);
const stateNew = {
valuesRaw: {
...valuesRaw,
carbon: valuesRaw.carbon + carbonDelta,
kvcmTotal: valuesRaw.kvcmTotal + kvcmDelta,
},
snapshots: {
...snapshots,
carbon: maybeUpdatedSnapshot(
snapshots.carbon,
valuesEffective.carbon,
valuesRaw.carbon,
time,
),
kvcmTotal: maybeUpdatedSnapshot(
snapshots.kvcmTotal,
valuesEffective.kvcmTotal,
valuesRaw.kvcmTotal,
time,
),
},
time,
};
return stateNew;
}
function executeChange(state, name, delta, time) {
if (name === "carbon") {
throw new Error("Use `executeSwap` or `executeRetire` to change `carbon`");
}
const { valuesRaw, snapshots } = state;
const valueEffective = computeEffectiveValue(
name,
valuesRaw,
snapshots,
time,
);
const stateNew = {
valuesRaw: { ...valuesRaw, [name]: valuesRaw[name] + delta },
snapshots: {
...snapshots,
[name]: maybeUpdatedSnapshot(
snapshots[name],
valueEffective,
valuesRaw[name],
time,
),
},
time,
};
return stateNew;
}
function computeEffectiveValues(valuesRaw, snapshots, time) {
const valuesEffective = {
carbon: computeEffectiveValue("carbon", valuesRaw, snapshots, time),
kvcmAlloc: computeEffectiveValue("kvcmAlloc", valuesRaw, snapshots, time),
k2Alloc: computeEffectiveValue("k2Alloc", valuesRaw, snapshots, time),
kvcmTotal: computeEffectiveValue("kvcmTotal", valuesRaw, snapshots, time),
k2Total: computeEffectiveValue("k2Total", valuesRaw, snapshots, time),
};
return valuesEffective;
}
function computeEffectiveValue(name, valuesRaw, snapshots, time) {
let valueEffective;
if (name === "carbon" || name === "kvcmTotal" || name === "k2Total") {
valueEffective = rateLimitedInv(valuesRaw[name], snapshots[name], time);
} else {
valueEffective = rateLimited(valuesRaw[name], snapshots[name], time);
}
return valueEffective;
}
function rateLimited(valueRaw, snapshot, time) {
const timeDelta = time - snapshot.time;
const valueLimit = snapshot.value * (1 + snapshot.rate * timeDelta);
const valueEffective = Math.min(valueRaw, valueLimit);
return valueEffective;
}
function rateLimitedInv(valueRaw, snapshot, time) {
const timeDelta = time - snapshot.time;
const valueLimit = snapshot.value / (1 + snapshot.rate * timeDelta);
const valueEffective = Math.max(valueRaw, valueLimit);
return valueEffective;
}
function maybeUpdatedSnapshot(snapshot, valueEffective, valueRaw, time) {
if (valueEffective === valueRaw) {
return { value: valueRaw, time: time, rate: snapshot.rate };
}
return snapshot;
}