Skip to content

Commit 6ebb898

Browse files
Merge pull request #41 from Piyushbijarania/ABI
Sync and add contract ABIs with base updates
2 parents dbf685c + 265fb4f commit 6ebb898

8 files changed

Lines changed: 252 additions & 39 deletions

File tree

app/[oracleId]/InteractionClient.tsx

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ function isHexAddress(value: string | null): value is `0x${string}` {
3636

3737
type PriceHistoryResult = readonly [readonly bigint[], readonly bigint[], readonly bigint[]]
3838

39-
const PRICE_DECIMALS = 8
39+
const PRICE_DECIMALS = 18
4040
const DISPLAY_PRECISION = 6
4141
const MAX_PRICE_POINTS = 20
4242

@@ -202,10 +202,10 @@ export default function OracleInteractionPage() {
202202
query: { enabled: !!oracleAddress && !!userAddress }
203203
})
204204

205-
const { data: lastSubmissionTimeData } = useReadContract({
205+
const { data: lastUpdatedData } = useReadContract({
206206
address: oracleAddress || undefined,
207207
abi: OracleAbi,
208-
functionName: 'lastSubmissionTime',
208+
functionName: 'lastUpdated',
209209
query: { enabled: !!oracleAddress }
210210
})
211211

@@ -380,8 +380,8 @@ export default function OracleInteractionPage() {
380380
if (tokenAllowanceData !== undefined) {
381381
setTokenAllowance(formatTokenAmount(tokenAllowanceData as bigint, 4))
382382
}
383-
if (lastSubmissionTimeData) {
384-
const timestamp = Number(lastSubmissionTimeData as bigint)
383+
if (lastUpdatedData) {
384+
const timestamp = Number(lastUpdatedData as bigint)
385385
const now = Math.floor(Date.now() / 1000)
386386
const diff = now - timestamp
387387
if (diff < 60) {
@@ -439,7 +439,7 @@ export default function OracleInteractionPage() {
439439
}
440440
}
441441

442-
}, [lockedTokensData, unlockedTokensData, userTokenBalanceData, tokenAllowanceData, formatTokenAmount, weightTokenDecimals, lastSubmissionTimeData, rewardData, halfLifeSecondsData, quorumData, operationLockingPeriodData, withdrawalLockingPeriodData, alphaData, depositTimestampData, lastOperationTimestampData])
442+
}, [lockedTokensData, unlockedTokensData, userTokenBalanceData, tokenAllowanceData, formatTokenAmount, weightTokenDecimals, lastUpdatedData, rewardData, halfLifeSecondsData, quorumData, operationLockingPeriodData, withdrawalLockingPeriodData, alphaData, depositTimestampData, lastOperationTimestampData])
443443

444444
// Early validation before calling the hook
445445
if (!oracleAddress || !chainIdValid) {
@@ -553,14 +553,11 @@ export default function OracleInteractionPage() {
553553

554554
try {
555555
setIsSubmitting(true)
556-
// Convert to int256 - the value should be a scaled integer
557-
// For example, if submitting 2500, multiply by 1e8 to get proper precision
558-
const valueAsFloat = parseFloat(submitValue)
559-
const valueAsInt = BigInt(Math.floor(valueAsFloat * (10**PRICE_DECIMALS)))
556+
// Parse to bigint using exact decimals to prevent JS precision loss
557+
const valueAsInt = parseUnits(submitValue, PRICE_DECIMALS)
560558

561559
console.log('Submitting value:', {
562560
original: submitValue,
563-
asFloat: valueAsFloat,
564561
asInt: valueAsInt.toString(),
565562
oracleAddress: oracleAddress,
566563
userAddress: userAddress
@@ -891,7 +888,7 @@ export default function OracleInteractionPage() {
891888
}
892889

893890
const attempt = async (account?: `0x${string}`) => {
894-
const { result } = await publicClient.simulateContract({
891+
const result = await publicClient.readContract({
895892
address: oracleAddress,
896893
abi: OracleAbi,
897894
functionName: fnName,

components/createOracle.tsx

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export default function CreateOracleIntegrated() {
3131
const [depositLock, setDepositLock] = useState<string>('3600')
3232
const [withdrawLock, setWithdrawLock] = useState<string>('3600')
3333
const [alpha, setAlpha] = useState<string>('1')
34+
const [defaultSampleSize, setDefaultSampleSize] = useState<string>('100')
3435

3536
// UI state
3637
const [loadingCreation, setLoadingCreation] = useState<boolean>(false)
@@ -51,6 +52,7 @@ export default function CreateOracleIntegrated() {
5152
depositLock?: string
5253
withdrawLock?: string
5354
alpha?: string
55+
defaultSampleSize?: string
5456
}>({})
5557

5658
// Pre-fill owner with connected wallet address
@@ -77,9 +79,10 @@ export default function CreateOracleIntegrated() {
7779
BigInt(Number(depositLock || 0)), // depositLockingPeriod
7880
BigInt(Number(withdrawLock || 0)), // withdrawalLockingPeriod
7981
BigInt(Number(reward || 0)), // rewardBps
80-
BigInt(alpha || "0"), // gamma
82+
BigInt(alpha && /^\d+$/.test(alpha) ? alpha : "0"), // gamma
83+
BigInt(defaultSampleSize && /^\d+$/.test(defaultSampleSize) ? defaultSampleSize : "100"), // defaultSampleSize
8184
] as const
82-
}, [name, description, weightToken, reward, halfLifeSeconds, quorumBps, depositLock, withdrawLock, alpha])
85+
}, [name, description, weightToken, reward, halfLifeSeconds, quorumBps, depositLock, withdrawLock, alpha, defaultSampleSize])
8386

8487
const validateInputs = () => {
8588
const newErrors: any = {}
@@ -94,8 +97,10 @@ export default function CreateOracleIntegrated() {
9497
if (!depositLock) newErrors.depositLock = 'Deposit lock period is required'
9598
if (!withdrawLock) newErrors.withdrawLock = 'Withdrawal lock period is required'
9699
if (!alpha) newErrors.alpha = 'Alpha is required'
100+
if (!defaultSampleSize) newErrors.defaultSampleSize = 'Default sample size is required'
97101

98102
if (Number(reward) < 0) newErrors.reward = 'Reward cannot be negative'
103+
if (Number(defaultSampleSize) <= 0) newErrors.defaultSampleSize = 'Default sample size must be greater than 0'
99104
if (Number(quorumBps) < 0 || Number(quorumBps) > 10000) newErrors.quorumBps = 'Quorum must be between 0 and 10000'
100105

101106
setErrors(newErrors)
@@ -607,6 +612,39 @@ export default function CreateOracleIntegrated() {
607612
/>
608613
{errors.alpha && <p className="text-red-400 text-xs">{errors.alpha}</p>}
609614
</div>
615+
616+
<div className="space-y-1">
617+
<div className="flex items-center gap-2 mb-2">
618+
<Label htmlFor="defaultSampleSize" className="text-slate-100 text-md">
619+
Default Lookback Sample Size *
620+
</Label>
621+
<button
622+
type="button"
623+
className="text-slate-300 hover:text-slate-100 transition-colors"
624+
onMouseEnter={() => setShowTooltip('defaultSampleSize')}
625+
onMouseLeave={() => setShowTooltip(null)}
626+
>
627+
<Info className="h-3 w-3" />
628+
</button>
629+
{showTooltip === 'defaultSampleSize' && (
630+
<div className="absolute z-10 bg-slate-800 text-slate-100 text-xs p-2 rounded shadow-lg mt-6">
631+
The default number of historical price points used for min/max calculations
632+
</div>
633+
)}
634+
</div>
635+
<Input
636+
id="defaultSampleSize"
637+
type="number"
638+
min={1}
639+
step={1}
640+
placeholder="100"
641+
value={defaultSampleSize}
642+
onChange={(e) => setDefaultSampleSize(e.target.value)}
643+
required
644+
className={`border-0 bg-slate-800/50 text-slate-100 placeholder:text-slate-400 text-md border border-blue-100 ${errors.defaultSampleSize ? 'border-red-500' : ''}`}
645+
/>
646+
{errors.defaultSampleSize && <p className="text-red-400 text-xs">{errors.defaultSampleSize}</p>}
647+
</div>
610648
</CardContent>
611649
</Card>
612650

components/oracle-card.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function OracleCard({ oracle }: OracleCardProps) {
3838
<div className="space-y-3 text-xs text-muted-foreground">
3939
<div className="flex items-center justify-between">
4040
<span className="uppercase tracking-wide text-muted-foreground/70">Last Submission</span>
41-
<span className="text-foreground/90 font-medium">{oracle.lastSubmissionTime}</span>
41+
<span className="text-foreground/90 font-medium">{oracle.lastUpdated}</span>
4242
</div>
4343
<div className="flex items-center justify-between">
4444
<span className="uppercase tracking-wide text-muted-foreground/70">Last Activity</span>

hooks/useOracles.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export interface Oracle {
3232
updateFrequency: string
3333
accuracy: string
3434
lastUpdate: string
35-
lastSubmissionTime: string
35+
lastUpdated: string
3636
lastTimestamp: string
3737
}
3838

@@ -74,7 +74,7 @@ export function useOracles() {
7474
const oraclePromises = oracleInfos.map(async (info: any, index: number) => {
7575
try {
7676
// Read oracle name and description from the contract
77-
const [name, description, lastSubmissionTime, lastTimestamp] = await Promise.all([
77+
const [name, description, lastUpdated, lastTimestamp] = await Promise.all([
7878
readContract(config, {
7979
address: info.oracle as `0x${string}`,
8080
abi: OracleAbi,
@@ -88,7 +88,7 @@ export function useOracles() {
8888
readContract(config, {
8989
address: info.oracle as `0x${string}`,
9090
abi: OracleAbi,
91-
functionName: 'lastSubmissionTime',
91+
functionName: 'lastUpdated',
9292
}).catch(() => BigInt(0)),
9393
readContract(config, {
9494
address: info.oracle as `0x${string}`,
@@ -109,7 +109,7 @@ export function useOracles() {
109109
updateFrequency: '1min',
110110
accuracy: '99.9%',
111111
lastUpdate: new Date().toISOString(),
112-
lastSubmissionTime: formatTimestamp(lastSubmissionTime as bigint),
112+
lastUpdated: formatTimestamp(lastUpdated as bigint),
113113
lastTimestamp: formatTimestamp(lastTimestamp as bigint),
114114
}
115115
} catch (err) {
@@ -126,7 +126,7 @@ export function useOracles() {
126126
updateFrequency: 'Unknown',
127127
accuracy: 'Unknown',
128128
lastUpdate: new Date().toISOString(),
129-
lastSubmissionTime: '—',
129+
lastUpdated: '—',
130130
lastTimestamp: '—',
131131
}
132132
}
@@ -185,7 +185,7 @@ export function useOracle(oracleAddress: string, targetChainId?: number) {
185185

186186
try {
187187
// Read oracle details from the contract
188-
const [name, description, lastSubmissionTime, lastTimestamp] = await Promise.all([
188+
const [name, description, lastUpdated, lastTimestamp] = await Promise.all([
189189
readContract(config, {
190190
address: oracleAddress as `0x${string}`,
191191
abi: OracleAbi,
@@ -199,7 +199,7 @@ export function useOracle(oracleAddress: string, targetChainId?: number) {
199199
readContract(config, {
200200
address: oracleAddress as `0x${string}`,
201201
abi: OracleAbi,
202-
functionName: 'lastSubmissionTime',
202+
functionName: 'lastUpdated',
203203
}).catch(() => BigInt(0)),
204204
readContract(config, {
205205
address: oracleAddress as `0x${string}`,
@@ -220,7 +220,7 @@ export function useOracle(oracleAddress: string, targetChainId?: number) {
220220
updateFrequency: '1min',
221221
accuracy: '99.9%',
222222
lastUpdate: new Date().toISOString(),
223-
lastSubmissionTime: formatTimestamp(lastSubmissionTime as bigint),
223+
lastUpdated: formatTimestamp(lastUpdated as bigint),
224224
lastTimestamp: formatTimestamp(lastTimestamp as bigint),
225225
})
226226
} catch (err) {
@@ -238,7 +238,7 @@ export function useOracle(oracleAddress: string, targetChainId?: number) {
238238
updateFrequency: 'Unknown',
239239
accuracy: 'Unknown',
240240
lastUpdate: new Date().toISOString(),
241-
lastSubmissionTime: '—',
241+
lastUpdated: '—',
242242
lastTimestamp: '—',
243243
})
244244
} finally {

utils/abi/ComposedOracle.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export const ComposedOracleAbi = [
2+
{
3+
"type": "constructor",
4+
"inputs": [
5+
{ "name": "_feedA", "type": "address", "internalType": "address" },
6+
{ "name": "_feedB", "type": "address", "internalType": "address" },
7+
{ "name": "_invertResult", "type": "bool", "internalType": "bool" },
8+
{ "name": "_defaultSampleSize", "type": "uint256", "internalType": "uint256" }
9+
],
10+
"stateMutability": "nonpayable"
11+
},
12+
13+
// Public immutable config
14+
{ "type": "function", "name": "feedA", "inputs": [], "outputs": [{ "type": "address", "internalType": "address" }], "stateMutability": "view" },
15+
{ "type": "function", "name": "feedB", "inputs": [], "outputs": [{ "type": "address", "internalType": "address" }], "stateMutability": "view" },
16+
{ "type": "function", "name": "invertResult", "inputs": [], "outputs": [{ "type": "bool", "internalType": "bool" }], "stateMutability": "view" },
17+
{ "type": "function", "name": "defaultSampleSize", "inputs": [], "outputs": [{ "type": "uint256", "internalType": "uint256" }], "stateMutability": "view" },
18+
19+
// Core view actions
20+
{ "type": "function", "name": "readValue", "inputs": [], "outputs": [{ "type": "uint256", "internalType": "uint256" }], "stateMutability": "view" },
21+
{ "type": "function", "name": "readLatestValue", "inputs": [], "outputs": [{ "type": "uint256", "internalType": "uint256" }], "stateMutability": "view" },
22+
{
23+
"type": "function",
24+
"name": "readValueInterval",
25+
"inputs": [],
26+
"outputs": [
27+
{ "name": "minValue", "type": "uint256", "internalType": "uint256" },
28+
{ "name": "maxValue", "type": "uint256", "internalType": "uint256" }
29+
],
30+
"stateMutability": "view"
31+
},
32+
{ "type": "function", "name": "lastUpdated", "inputs": [], "outputs": [{ "type": "uint256", "internalType": "uint256" }], "stateMutability": "view" },
33+
{ "type": "function", "name": "isBlacklisted", "inputs": [{ "name": "target", "type": "address", "internalType": "address" }], "outputs": [{ "type": "bool", "internalType": "bool" }], "stateMutability": "view" },
34+
35+
// Errors
36+
{ "type": "error", "name": "DivisionByZero", "inputs": [] },
37+
{ "type": "error", "name": "InvalidFeedAddress", "inputs": [] },
38+
{ "type": "error", "name": "BlacklistedCaller", "inputs": [] },
39+
{ "type": "error", "name": "EmptyHistory", "inputs": [] },
40+
{ "type": "error", "name": "InvalidSampleSize", "inputs": [] }
41+
] as const;

0 commit comments

Comments
 (0)