Saltar al contenido principal

ClockTower Subscribe

Allowed Time Ranges

  • Weekly Subscriptions -- 1 - 7 (Weekdays)
  • Monthly Subscriptions -- 1 - 28 (Day of Month)
  • Quarterly Subscriptions -- 1 - 90 (Day of Quarter)
  • Yearly Subscription -- 1 - 365 (Day of Year (not including leap days))

Future Transaction Range

  • Future Transactions -- Unixtime / 3600 (Unix Hours)

Data Structures

The following are the data structs required by external functions:

Subscription Data

Structs

Subscription
 struct Subscription {
bytes32 id;
uint amount;
address provider;
address token;
bool exists;
bool cancelled;
Frequency frequency;
uint16 dueDay;
string description;
}
NameTypeDescription
idbytes32Unique hash generated for each subscription
amountuintAmount of subscription in wei
provideraddressAddress of the creator of the subscription
tokenaddressERC20 address of token used in subscription
existsboolTrue if subscription exists
cancelledboolTrue if subscription is cancelled
frequencyFrequencyFrequency
dueDayuint16Day in frequency range when subscription is paid
descriptionstringDescription of subscription
SubView
 struct SubView {
Subscription subscription;
Status status;
uint totalSubscribers;
}
NameTypeDescription
subscriptionSubscriptionSubscription
statusStatusStatus
totalsubscribersuintTotal number of subscribers
FeeEstimate
struct FeeEstimate {
uint fee;
address token;
}
NameTypeDescription
feeuintFee amount in wei
tokenaddressERC20 address of token
SubscriberView
struct SubscriberView {
address subscriber;
uint feeBalance;
}
NameTypeDescription
subscriberaddressSubscriber address
feeBalanceuintFee balance of subscriber in wei
Time
struct Time {
uint16 day;
uint16 weekDay;
uint16 quarterDay;
uint16 yearDay;
uint16 year;
uint16 month;
}
NameTypeDescription
dayuint16Day of month
weekDayuint16Day of week
quarterDayuint16Day of quarter
yearDayuint16Day of year
yearuint16Year
monthuint16Month

Enums

(Enum values are represented by numbers starting at zero)

Frequency
enum Frequency {
WEEKLY,
MONTHLY,
QUARTERLY,
YEARLY
}
ValueDescription
0WEEKLY
1MONTHLY
2QUARTERLY
3YEARLY
Status
enum Status {
ACTIVE,
CANCELLED,
UNSUBSCRIBED
}
ValueDescription
0ACTIVE
1CANCELLED
2UNSUBSCRIBED
SubEvent
enum SubEvent {
PAID,
FAILED,
SUBSCRIBED,
UNSUBSCRIBED,
FEEFILL,
REFUND
}
ValueDescription
0PAID
1FAILED
2SUBSCRIBED
3UNSUBSCRIBED
4FEEFILL
5REFUND
ProvEvent
enum ProvEvent {
CREATE,
CANCEL,
PAID,
FAILED,
REFUND
}
ValueDescription
0CREATE
1CANCEL
2PAID
3FAILED
4REFUND

Global Variables

Subscription Global Variables

NameTypeDescriptionFormat
callerFeeuintPercentage paid to caller on remits10000 = No fee, 10100 = 1%, 10001 = 0.01%
systemFeeuintFlat fee paid to admin account when systemFee bool is truewei
maxGasPriceuintMaximum gas value for remit functiongwei
maxRemitsuintMaximum number of remits per remit function (usually based on block max)
adminaddressAddress for admin account
nextUncheckedDayuint40Last time remit ws calledUnix epoch time

Events

Subscription Events

SubscriberLog
event SubscriberLog(
bytes32 indexed id,
address indexed subscriber,
uint40 timestamp,
uint amount,
SubEvent indexed subEvent
)

Log emitted during subscriber events

NameTypeIndexedDescription
idbytes32✔️Unique Subscription id
subscriberaddress✔️Address of subscriber
timestampuint40Unix Epoch timestamp
amountuintERC20 subscription amount in wei
subEventSubEvent✔️SubEvent
CallerLog
event CallerLog(
uint40 timestamp,
uint40 checkedDay,
address indexed caller,
bool isFinished
)

Log emitted during Caller events

NameTypeIndexedDescription
timestampuint40Unix epoch timestamp
checkedDayuint40Day in frequency range checked by Caller
calleraddress✔️Address of caller
isFinishedboolShows if Caller is done
ProviderLog
event ProviderLog(
bytes32 indexed id,
address indexed provider,
uint40 timestamp,
uint amount,
ProvEvent indexed provEvent
)

Log emitted during Provider events

NameTypeIndexedDescription
idbytes32✔️Unique subscription id
provideraddress✔️Provider address
timestampuint40Unix epoch timestamp
amountuint0 unless refund
provEventProvEvent✔️ProvEvent

Functions

Subscription Functions

Input Functions

createSubscription
function createSubscription(
uint amount,
address token,
string description,
Frequency frequency,
uint16 dueDay
) external payable

Allows provider to create a new subscription.

Parameters:

NameTypeDescription
amountuintAmount of subscription in wei
tokenaddressERC20 address of token used in subscription
descriptionstringDescription of subscription
frequencyFrequencyFrequency
dueDayuint16Day in range based on frequency when subscription is paid
subscribe
function subscribe(
Subscription subscription
) external payable

Allows user to subscribe to subscription

Parameters:

NameTypeDescription
subscriptionSubscriptionSubscription
unsubscribe
function unsubscribe(
bytes32 id
) external payable

Allows user to unsubscribe from subscription.

msg.sender must be subscribed to subscription.

Parameters:

NameTypeDescription
idbytes32Unique subscription id
unsubscribeByProvider
function unsubscribeByProvider(
address subscriber,
bytes32 id
) external

Allows provider to cancel subscriber from their created subscriptions.

msg.sender must be creator of subscription and subscriber must be subscribed.

Parameters:

NameTypeDescription
subscriberaddressSubscriber address
idbytes32Unique subscription id
cancelSubscription
function cancelSubscription(
Subscription subscription
) external

Allows provider to cancel subscription. All existing subscribers will no longer be charged

msg.sender must be creator of subscription

Parameters:

NameTypeDescription
subscriptionSubscriptionSubscription

View Functions

getAccountSubscriptions
function getAccountSubscriptions(
bool bySubscriber,
address account
) returns (SubView[])

Returns an array of objects containing subscription and status by account.

If bySubscriber is true it gets a list of subscriptions account is subscribed to. If false it gets a list of subscriptions account created as the provider.

Parameters:

NameTypeDescription
bySubscriberboolSee above description of bool
accountaddressAccount address for subscriptions

Return Value:

NameTypeDescription
SubView[]SubViewArray of Subview structs
getTotalSubscribers
function getTotalSubscribers(
) returns (uint)

Returns total number of subscribers so user can iterate through accountLookup() array.

Return Value:

NameTypeDescription
uintuintTotal amount of subscribers in contract
getSubscribersById
function getSubscribersById(
bytes32 id
) external view returns (SubscriberView[] memory)

Returns array of objects containing subscriber info.

Parameters:

NameTypeDescription
idbytes32Unique subscription id

Return Value:

NameTypeDescription
SubscriberView[]SubscriberViewArray of SubscriberView structs
getSubByIndex
function getSubByIndex(
bytes32 id,
Frequency frequency,
uint16 dueDay
) view public returns(Subscription subscription)

Returns subscription object

Parameters:

NameTypeDescription
idbytes32Unique subscription id
frequencyFrequencyFrequency
dueDayuint16Day in range based on frequency when subscription is paid

Return Value:

NameTypeDescription
subscriptionSubscriptionSubscription
feeEstimate
function feeEstimate(

) returns(FeeEstimate[])

Returns an array of objects showing the next batch of remits and possible fees

Return Value:

NameTypeDescription
FeeEstimate[]FeeEstimateArray of FeeEstimate structs

Time Functions

unixToTime
function unixToTime(
uint unix
) returns(Time time)

Converts a unix time value to Time struct

Parameter:

NameTypeDescription
unixuintUnix time value

Return Value:

NameTypeDescription
timeTimeTime struct

Code:

uint _days = unix/86400;
uint16 day;
uint16 yearDay;

int __days = int(_days);

int L = __days + 68569 + 2440588;
int N = 4 * L / 146097;
L = L - (146097 * N + 3) / 4;
int _year = 4000 * (L + 1) / 1461001;
L = L - 1461 * _year / 4 + 31;
int _month = 80 * L / 2447;
int _day = L - 2447 * _month / 80;
L = _month / 11;
_month = _month + 2 - 12 * L;
_year = 100 * (N - 49) + _year + L;

uint uintyear = uint(_year);
uint month = uint(_month);
uint uintday = uint(_day);

day = uint16(uintday);

uint dayCounter;

//loops through months to get current day of year
for(uint monthCounter = 1; monthCounter <= month; monthCounter++) {
if(monthCounter == month) {
dayCounter += day;
} else {
dayCounter += getDaysInMonth(uintyear, month);
}
}

yearDay = uint16(dayCounter);

//gets day of quarter
time.quarterDay = getdayOfQuarter(yearDay, uintyear);
time.weekDay = getDayOfWeek(unix);
time.day = day;
time.yearDay = yearDay;
isLeapYear
function isLeapYear(
uint year
) returns (bool leapYear)

Checks if year is a leap year

Parameter:

NameTypeDescription
yearuintNumber of year in Gregorian Calendar

Return Value:

NameTypeDescription
leapYearboolTrue if leap year

Code:

leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
getDaysInMonth
function getDaysInMonth(
uint year,
uint month
) returns (uint daysInMonth)

Returns the number of days in the month based on Gregorian year and month calendar values

Parameters:

NameTypeDescription
yearuintNumber of year in Gregorian Calendar
monthuintNumber of month in Gregorian Calendar

Return Value:

NameTypeDescription
daysInMonthuintNumber of days in the month

Code:

if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
daysInMonth = 31;
} else if (month != 2) {
daysInMonth = 30;
} else {
daysInMonth = isLeapYear(year) ? 29 : 28;
}
getDaysOfWeek
function getDaysofWeek(
uint unixTime
) returns (uint16 dayOfWeek)

Returns the number of the day of the week

Parameter:

NameTypeDescription
unixTimeuintUnix time value

Return Value:

NameTypeDescription
dayOfWeekuint16Day of the week (1 = Monday, 7 = Sunday)

Code:

uint _days = unixTime / 86400;
uint dayOfWeekuint = (_days + 3) % 7 + 1;
dayOfWeek = uint16(dayOfWeekuint);
getdayOfQuarter
function getdayOfQuarter(
uint yearDays,
uint year
) returns (uint16 quarterDay)

Returns the day of the quarter range day based the year and the day of the year

Parameters:

NameTypeDescription
yearDaysuintDay of the year (Between 1 - 365)
yearuintNumber of year in Gregorian Calendar

Return Value:

NameTypeDescription
quarterDayuint16Day of the quarter (1 - 90)

Code:

uint leapDay;
if(isLeapYear(year)) {
leapDay = 1;
} else {
leapDay = 0;
}

if(yearDays <= (90 + leapDay)) {
quarterDay = uint16(yearDays);
} else if((90 + leapDay) < yearDays && yearDays <= (181 + leapDay)) {
quarterDay = uint16(yearDays - (90 + leapDay));
} else if((181 + leapDay) < yearDays && yearDays <= (273 + leapDay)) {
quarterDay = uint16(yearDays - (181 + leapDay));
} else {
quarterDay = uint16(yearDays - (273 + leapDay));
}
unixToDays
function unixToDays (
uint40 unixTime
) returns (uint40 dayCount)

Returns the amount of days (rounded down) since unix epoch based on a provided unix time

Parameter:

NameTypeDescription
unixTimeuintUnix time value

Return Value:

NameTypeDescription
dayCountuint16Number of days (rounded down) since unix epoch

Code:

dayCount = unixTime/86400;
prorate
function prorate (
uint unixTime,
uint40 dueDay,
uint fee,
uint8 frequency) returns (uint)

Returns prorated amount of subscription based upons subscription parameters

Parameters:

NameTypeDescription
unixTimeuintUnix time value
dueDayuint40Day in frequency range when subscription is paid
feeuintFee amount in wei
frequencyuint8Frequency

Return Value:

NameTypeDescription
uintuintProrated amount of susbcription in wei

Code:

Time memory time = unixToTime(unixTime);
uint currentDay;
uint max;
uint lastDayOfMonth;

//sets maximum range day amount
if(frequency == 0) {
currentDay = time.weekDay;
max = 7;
//monthly
} else if (frequency == 1){
//calculates maximum days in current month
lastDayOfMonth = getDaysInMonth(time.year, time.month);
currentDay = time.dayOfMonth;
max = lastDayOfMonth;
//quarterly and yearly
} else if (frequency == 2) {
currentDay = getdayOfQuarter(time.yearDay, time.year);
max = 90;
//yearly
} else if (frequency == 3) {
currentDay = time.yearDay;
max = 365;
}

//monthly
if(frequency == 1) {
uint dailyFee = (fee * 12 / 365);
if(dueDay != currentDay && currentDay > dueDay){
//dates split months
fee = (dailyFee * (max - (currentDay - dueDay)));
} else if (dueDay != currentDay && currentDay < dueDay) {
//both dates are in the same month
fee = (dailyFee * (dueDay - currentDay));
}
}
//weekly quarterly and yearly
else if(frequency == 0 || frequency == 2 || frequency == 3) {
if(dueDay != currentDay && currentDay > dueDay){
fee = (fee / max) * (max - (currentDay - dueDay));
} else if (dueDay != currentDay && currentDay < dueDay) {
fee = (fee / max) * (dueDay - currentDay);
}
}

return fee;